package com.suning.sawp.service.impl.model;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.gson.reflect.TypeToken;
import com.suning.rsf.consumer.ServiceLocator;
import com.suning.rsf.pcss.dto.item.RsfItemInfoResponseDto;
import com.suning.rsf.pcss.dto.itemList.RsfItemInfoListResponseDto;
import com.suning.rsf.pcss.dto.itemList.RsfListRequestDto;
import com.suning.rsf.pcss.dto.itemList.RsfRequestDto;
import com.suning.sawp.cache.RedisClient;
import com.suning.sawp.constants.CacheKeyConstants;
import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.ErrorCodeConstants;
import com.suning.sawp.constants.ExportConstants;
import com.suning.sawp.constants.LoggerConstants;
import com.suning.sawp.constants.ModelClusterErrorConstants;
import com.suning.sawp.dto.common.QueryClusterInfoList;
import com.suning.sawp.dto.common.QueryClusterList;
import com.suning.sawp.dto.common.QueryResult;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.mainpush.StoreManDto;
import com.suning.sawp.dto.precharge.CommonRtn;
import com.suning.sawp.intf.model.BrandBean;
import com.suning.sawp.intf.model.BrandInfo;
import com.suning.sawp.intf.model.CategoryBean;
import com.suning.sawp.intf.model.CommInfoBean;
import com.suning.sawp.intf.model.DownloadModelListBean;
import com.suning.sawp.intf.model.ModelBean;
import com.suning.sawp.intf.model.ModelCateBrand;
import com.suning.sawp.intf.model.ModelCategoryBrandInfoBean;
import com.suning.sawp.intf.model.ModelCluster;
import com.suning.sawp.intf.model.ModelClusterInfo;
import com.suning.sawp.intf.model.ModelCommClusterVo;
import com.suning.sawp.intf.model.ModelCommodityBaseInfo;
import com.suning.sawp.intf.model.ModelConstant;
import com.suning.sawp.intf.model.ModelEffectiveness;
import com.suning.sawp.intf.model.ModelErrorConstant;
import com.suning.sawp.intf.model.ModelExptBean;
import com.suning.sawp.intf.model.ModelManageDaoService;
import com.suning.sawp.intf.model.ModelManageService;
import com.suning.sawp.intf.model.ModelTaskAssignDetailsBean;
import com.suning.sawp.intf.model.ModelTaskAssignVo;
import com.suning.sawp.intf.model.ModelTaskBean;
import com.suning.sawp.intf.model.ModelTaskHasAssignVo;
import com.suning.sawp.intf.model.ModelTaskInfoVo;
import com.suning.sawp.intf.model.ModelTaskMainBean;
import com.suning.sawp.intf.model.ModelTaskMonitorDetailVo;
import com.suning.sawp.intf.model.ModelTaskMonitorVo;
import com.suning.sawp.intf.model.ModelTaskNoAssignVo;
import com.suning.sawp.intf.model.ModelZoneInfo;
import com.suning.sawp.intf.model.OrgInfo;
import com.suning.sawp.intf.model.OrgTreeBean;
import com.suning.sawp.intf.model.PriceTagDetail;
import com.suning.sawp.intf.model.SaleModelExptBean;
import com.suning.sawp.intf.model.TaskDetailBean;
import com.suning.sawp.intf.precharge.SequenceSerivce;
import com.suning.sawp.intf.store.StoreInfoService;
import com.suning.sawp.intf.storeman.StoreManService;
import com.suning.sawp.intf.util.EmailUtilsService;
import com.suning.sawp.intf.util.OSSFileService;
import com.suning.sawp.po.model.ModelCategoryBrandInfo;
import com.suning.sawp.po.model.ModelTaskMain;
import com.suning.sawp.po.store.StoreInfo;
import com.suning.sawp.po.util.OSSFileResult;
import com.suning.sawp.service.util.BeanUtil;
import com.suning.sawp.service.util.DJStringUtils;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.ExcelUtils;
import com.suning.sawp.service.util.ExportFileUtil;
import com.suning.sawp.service.util.GsonUtils;
import com.suning.sawp.service.util.MainPushExcelHandle;
import com.suning.sawp.service.util.RedisCacheUtils;
import com.suning.sawp.service.util.SCMConfigUtil;

@Service
public class ModelManageServiceImpl implements ModelManageService {

    /**
     * 日志
     */
    private static final Logger   LOGGER            = LoggerFactory
                                                            .getLogger(LoggerConstants.SAWP_SERVICE);

    @Resource
    ModelManageDaoService         modelManageDaoService;

    @Resource
    StoreInfoService              storeInfoService;

    @Resource
    ModelCommodityInfoServiceImpl modelCommodityInfoService;

    @Autowired
    RedisClient                   redisClient;

    @Resource
    ModelCommClusterServiceImpl   modelCommClusterService;

    @Resource
    StoreManService               storeManService;

    @Resource
    RedisCacheUtils               cacheUtils;
    
    @Autowired
    SequenceSerivce sequenceSerivce;
    
    @Autowired
    ModelTaskNewServiceImpl modelTaskNewService;
    
    @Resource
    OSSFileService ossFileService;
    
    @Resource
    EmailUtilsService emailUtilsService;
    
    @Resource
    ExportFileUtil exportFileUtil;

    private static final String   DATE_FORMAT       = "yyyy-MM-dd";

    private static final String   MONTH_FORMAT      = "yyyy.MM";

    private static final String   FULL_DATE_FORMAT  = "yyyy-MM-dd HH:mm:ss";

    private static final String   END_TIME_SUFFIXES = " 23:59:59";
    
    /**
     * 自增序列key
     */
    private static final String SEQUENCE_CLUSTER_CODE_KEY = "MODE_SEQUENCE_CLUSTER_CODE";
    
    /**
     * 接口执行成功码
     */
    private static String SUCCESS = "0";
    
    /**
     * 样机清单每天导出次数上限
     */
    private static final int EXPORT_MODEL_TIMES_LIMIT = 50;
    
    /**
     * 商品簇导入时，最大限制条数
     */
    private static final int IMPORT_EXCEL_DATA_LIMT = 20000;
    
    /**
     * 文件上传成功
     */
    private static final String FILE_UPLOAD_SUCCESS = "1";
    
    
    private static final String MODEL_MONITOR_HQ = "all";
    
    /**
     * 导出查询
     */
    private static final String EXPORT_SEARCH = "2";
   
    
    /**
     * 商品RSF接口服务
     */
    com.suning.rsf.pcss.service.ProductService productService = ServiceLocator
            .getService(com.suning.rsf.pcss.service.ProductService.class, null);
    
    @Override
    public ReturnMsg<QueryResult<ModelBean>> queryModelList(String regionCode, String branchCode, String commCode,
            String storeCode, Integer pageNo, Integer pageSize,String status,String categoryCode,String brandCode) {
        ReturnMsg<QueryResult<ModelBean>> ret = new ReturnMsg<QueryResult<ModelBean>>();
        QueryResult<ModelBean> qr = new QueryResult<ModelBean>();
        List<ModelBean> list = new ArrayList<ModelBean>();
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? 10 : pageSize;
        int num = modelManageDaoService.queryModelCountByStoreCode(regionCode, branchCode, commCode, storeCode,status, categoryCode,brandCode);
        if (num > 0) {
            list = modelManageDaoService.queryModelByStoreCode(regionCode, branchCode, commCode, storeCode, pageNo,
                    pageSize,status, categoryCode, brandCode);
        }
        qr.setRecords(list);
        qr.setTotalSize(num);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<QueryResult<ModelExptBean>> queryModelExptList(String regionCode, String branchCode,
            String storeCode, Integer pageNo, Integer pageSize) {
        ReturnMsg<QueryResult<ModelExptBean>> ret = new ReturnMsg<QueryResult<ModelExptBean>>();
        QueryResult<ModelExptBean> qr = new QueryResult<ModelExptBean>();
        List<ModelExptBean> list = new ArrayList<ModelExptBean>();
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? 10 : pageSize;
        int num = modelManageDaoService.queryModelExptCountByStoreCode(regionCode, branchCode, storeCode);
        if (num > 0) {
            list = modelManageDaoService.queryModelExptByStoreCode(regionCode, branchCode, storeCode, pageNo, pageSize, null);
        }
        qr.setRecords(list);
        qr.setTotalSize(num);
        ret.setData(qr);
        return ret;
    }

    /**
     * 财务样机异常清单列表
     */
    @Override
    public ReturnMsg<QueryResult<SaleModelExptBean>> querySaleModelExptList(String regionCode, String branchCode,
            String storeCode, Integer pageNo, Integer pageSize, Integer isInStorage) {
        ReturnMsg<QueryResult<SaleModelExptBean>> ret = new ReturnMsg<QueryResult<SaleModelExptBean>>();
        QueryResult<SaleModelExptBean> qr = new QueryResult<SaleModelExptBean>();
        List<SaleModelExptBean> list = new ArrayList<SaleModelExptBean>();
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? 10 : pageSize;
        int num = modelManageDaoService.querySaleModelExptCountByStoreCode(regionCode, branchCode, storeCode,
                isInStorage);
        if (num > 0) {
            list = modelManageDaoService.querySaleModelExptByStoreCode(regionCode, branchCode, storeCode, pageNo,
                    pageSize, isInStorage, null);
        }
        qr.setRecords(list);
        qr.setTotalSize(num);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<QueryResult<ModelTaskBean>> queryTaskList(String taskStartTime,
            String taskEndTime, Set<Integer> taskType, Integer pageNo, Integer pageSize, String taskStatus) {
        ReturnMsg<QueryResult<ModelTaskBean>> ret = new ReturnMsg<QueryResult<ModelTaskBean>>();
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? 10 : pageSize;
        QueryResult<ModelTaskBean> qr = new QueryResult<ModelTaskBean>();
        int num = modelManageDaoService.queryTaskListCount(taskStartTime, taskEndTime, taskType,taskStatus);
        List<ModelTaskBean> list = new ArrayList<ModelTaskBean>();
        if (num > 0) {
            list = modelManageDaoService.queryTaskList(taskStartTime, taskEndTime, taskType,
                    pageNo, pageSize, taskStatus);
        }
        qr.setRecords(list);
        qr.setTotalSize(num);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<List<CategoryBean>> queryAllCate() {
        ReturnMsg<List<CategoryBean>> ret = new ReturnMsg<List<CategoryBean>>();
        List<CategoryBean> list = modelManageDaoService.queryAllCate();
        ret.setData(list);
        return ret;
    }

    @Override
    public ReturnMsg<List<ModelCateBrand>> queryBrandCate() {
        ReturnMsg<List<ModelCateBrand>> ret = new ReturnMsg<List<ModelCateBrand>>();
        List<ModelCateBrand> cateBrandList = new ArrayList<ModelCateBrand>();
        //查询所有样机的品类品牌，走缓存
        String value = redisClient.get(CacheKeyConstants.ALL_CATE_BRAND);
        if (null != value) {
            cateBrandList = GsonUtils.fromJson(value, new TypeToken<List<ModelCateBrand>>() {
            });
        } else {
            List<BrandBean> list = modelManageDaoService.queryAllBrand();
            cateBrandList = getModelCateBrandList(list);
            redisClient.set(CacheKeyConstants.ALL_CATE_BRAND,
                    DJStringUtils.GSON.toJson(cateBrandList));
            redisClient.expire(CacheKeyConstants.ALL_CATE_BRAND,
                    CacheKeyConstants.REGION_ALL_EXPIRE_TIME);
        }
        ret.setData(cateBrandList);
        return ret;
    }

    private List<ModelCateBrand> getModelCateBrandList(List<BrandBean> list) {
        Map<String, ModelCateBrand> map = new HashMap<String, ModelCateBrand>();
        for (BrandBean brand : list) {
            if (map.get(brand.getCategoryCode()) == null) {
                ModelCateBrand cateBrand = new ModelCateBrand();
                cateBrand.setCategoryCode(brand.getCategoryCode());
                cateBrand.setCategoryName(brand.getCategoryName());
                List<BrandBean> brandList = new ArrayList<BrandBean>();
                brandList.add(brand);
                cateBrand.setBrandList(brandList);
                map.put(brand.getCategoryCode(), cateBrand);
            } else {
                ModelCateBrand modelCateBrand = map.get(brand.getCategoryCode());
                modelCateBrand.getBrandList().add(brand);
            }
        }
        return new ArrayList<ModelCateBrand>(map.values());
    }

    @Override
    public ReturnMsg<List<OrgTreeBean>> queryOrgList(String regionCode, String branchCode, String storeCode,
            Integer storeType,Long taskId) {
        ReturnMsg<List<OrgTreeBean>> ret = new ReturnMsg<List<OrgTreeBean>>();
        if (storeType == null) {
            storeType = OrgTreeBean.STORE_TYPE.TYPE_ALL;
        }
        List<OrgTreeBean> orgList = new ArrayList<OrgTreeBean>();
        String key = String.valueOf(storeType);
        if(taskId != null){
            key = key+String.format(CacheKeyConstants.MODEL_ORG_TREE_TASK, taskId);
        } else if (StringUtils.isNotBlank(regionCode)) {
            key = key+String.format(CacheKeyConstants.MODEL_ORG_TREE_REGION, regionCode);
        } else if (StringUtils.isNotBlank(branchCode)) {
            key = key+String.format(CacheKeyConstants.MODEL_ORG_TREE_BRANCH, branchCode);
        } else if (StringUtils.isNotBlank(storeCode)) {
            key = key+String.format(CacheKeyConstants.MODEL_ORG_TREE_STORE, storeCode);
        } 
        String value = redisClient.hget(CacheKeyConstants.STORE_TREE, key);
        if (null != value) {
            orgList = GsonUtils.fromJson(value, new TypeToken<List<OrgTreeBean>>() {
            });
        } else {
            OrgTreeBean orgMain = new OrgTreeBean();
            //根节点为全国
            orgMain.setId("0");
            orgMain.setLevel(OrgInfo.ORG_LEVEL.HQ_LEVEL);
            orgMain.setPid("-1");
            orgMain.setText("全国");
            orgList.add(orgMain);
            List<StoreInfo> storeList = new ArrayList<StoreInfo>();
            //判断查询门店类型 电器店  服务站  全部 有任务Id，优先取任务下门店列表
            if(taskId != null){
                List<String> storeCodeList = modelManageDaoService.queryTaskStoreCodeList(taskId);
                storeList = storeInfoService.queryStoreByStoreCodes(storeCodeList);
            }else if (storeType == OrgTreeBean.STORE_TYPE.TYPE_STORE) {
                storeList = storeInfoService.queryStoreByStoreType(
                        OrgTreeBean.STORE_TYPE.STORE_TYPE_SERVICE, regionCode, branchCode, storeCode, false);
            } else if (storeType == OrgTreeBean.STORE_TYPE.TYPE_SERVICE) {
                storeList = storeInfoService.queryStoreByStoreType(
                        OrgTreeBean.STORE_TYPE.STORE_TYPE_SERVICE, regionCode, branchCode, storeCode, true);
            } else if (storeType == OrgTreeBean.STORE_TYPE.TYPE_ALL) {
                storeList = storeInfoService.queryStoreByStoreType(null, regionCode, branchCode, storeCode,
                        true);
            }
            //组装返回
            if (CollectionUtils.isNotEmpty(storeList)) {
                Set<String> regionSet = new HashSet<String>();
                Set<String> branchSet = new HashSet<String>();
                for (StoreInfo store : storeList) {
                    if (!regionSet.contains(store.getRegionCode())) {
                        OrgTreeBean org = new OrgTreeBean();
                        org.setId(store.getRegionCode());
                        org.setLevel(OrgInfo.ORG_LEVEL.REGION_LEVEL);
                        org.setPid(String.valueOf(OrgInfo.ORG_LEVEL.HQ_LEVEL));
                        org.setText(store.getRegionName());
                        orgList.add(org);
                        regionSet.add(store.getRegionCode());
                    }
                    if (!branchSet.contains(store.getSaleBranchCode())) {
                        OrgTreeBean org = new OrgTreeBean();
                        org.setId(store.getSaleBranchCode());
                        org.setLevel(OrgInfo.ORG_LEVEL.BRANCH_LEVEL);
                        org.setPid(store.getRegionCode());
                        org.setText(store.getBranchName());
                        orgList.add(org);
                        branchSet.add(store.getSaleBranchCode());
                    }
                    OrgTreeBean org = new OrgTreeBean();
                    org.setId(store.getStoreCode());
                    org.setLevel(OrgInfo.ORG_LEVEL.STORE_LEVEL);
                    org.setPid(store.getSaleBranchCode());
                    org.setText(store.getStoreName());
                    orgList.add(org);
                }
            }
            redisClient.hset(CacheKeyConstants.STORE_TREE, key, DJStringUtils.GSON.toJson(orgList));
            redisClient.expire(CacheKeyConstants.STORE_TREE,
                    CacheKeyConstants.REGION_ALL_EXPIRE_TIME);
        }
        ret.setData(orgList);
        return ret;
    }

    @SuppressWarnings("unchecked")
    @Transactional
    @Override
    public void saveModelList(String storeCode, List<PriceTagDetail> commList) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        StoreInfo store = storeInfoService.queryStoreByCode(storeCode);
        if (store == null) {
            return;
        }
        List<String> brandCodes = modelManageDaoService.queryStoreBrandCode(storeCode);
        Set<String> brand9Code = new HashSet<String>();
        for (PriceTagDetail comm : commList) {
            Map<String, Object> insertMap = new HashMap<String, Object>();
            // 查询商品详细信息
            ModelCommodityBaseInfo baseInfo = modelCommodityInfoService.queryCommodityBaseInfo(comm
                    .getCmmdtyCode());
            // 与产品合计，样机-门店-品类-品牌表不接收非电器八大品类的品牌  12061818
            if (baseInfo != null && ConfigConstants.DEFAULT_CATE_MAP.containsKey(baseInfo.getCateCode())) {
                if (!brand9Code.contains(baseInfo.getBranch9code())) {
                    // 判断门店是否已经有此品牌
                    if (!brandCodes.contains(baseInfo.getBranch9code())) {
                        ModelCategoryBrandInfo cateBrand = new ModelCategoryBrandInfo();
                        cateBrand.setBranch4code(baseInfo.getBranch4code());
                        cateBrand.setBranch9code(baseInfo.getBranch9code());
                        cateBrand.setBranchName(baseInfo.getBranchName());
                        cateBrand.setCateCode(baseInfo.getCateCode());
                        cateBrand.setCateName(baseInfo.getCateName());
                        cateBrand.setStoreCode(storeCode);
                        // 插入品牌信息表
                        modelManageDaoService.insertModelCateBrand(cateBrand);
                        redisClient.del(CacheKeyConstants.ALL_CATE_BRAND);
                        // 判断门店是否需要增补品牌任务，如果满足增补品牌任务的条件，则增补任务
                        suppleAddStoreBrandTask(baseInfo, storeCode, comm);
                    }
                    brand9Code.add(baseInfo.getBranch9code());
                }
                insertMap.put("branch4code", baseInfo.getBranch4code());
                insertMap.put("branch9code", baseInfo.getBranch9code());
                insertMap.put("branchName", baseInfo.getBranchName());
                insertMap.put("cateCode", baseInfo.getCateCode());
                insertMap.put("cateName", baseInfo.getCateName());
                insertMap.put("commName", baseInfo.getCommName());
                insertMap.put("commCode", comm.getCmmdtyCode());
                insertMap.put("storageCode",
                        "1".equals(comm.getCounterFlag()) ? ModelBean.STORAGE_TYPE.COUNTER_TYPE
                                : ModelBean.STORAGE_TYPE.MODEL_TYPE);
                insertMap.put("storeCode", storeCode);
                insertMap.put("storeName", store.getStoreName());
                insertMap.put("disCode", store.getRegionCode());
                insertMap.put("disName", store.getRegionName());
                insertMap.put("orgCode", store.getSaleBranchCode());
                insertMap.put("orgName", store.getBranchName());
                insertMap.put("storeType", store.getStoreTypeCode());
                list.add(insertMap);
            } else {
                LOGGER.error("ModelManageServiceImpl.saveModelList.CommCode: " + comm.getCmmdtyCode() + ",baseInfo:" + baseInfo);
            }
        }
        if (list.size() > 0) {
            // 批量插入样机清单
            modelManageDaoService.batchInsertModelList(list.toArray(new HashMap[list.size()]));
        }
    }

    /**
     * 
     * 功能描述: 增补门店品牌任务<br>
     * 〈功能详细描述〉
     *
     * @param storeCode 门店编码
     * @param brandCode 品牌编码
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void suppleAddStoreBrandTask(ModelCommodityBaseInfo baseInfo,String storeCode, PriceTagDetail comm) {
        // 1、判断此时门店此品牌下是否存在正在进行中的盘点任务
        List<ModelTaskBean> tasks = modelManageDaoService.queryExistTaskIdsByStoreCode(storeCode, baseInfo.getBranch9code());
        // 2、如果存在正在进行中的盘点任务, 增补至任务明细表中MODEL_TASK_ASSIGN_DETAILS
        if (CollectionUtils.isNotEmpty(tasks)) {
            StoreInfo store = storeInfoService.queryStoreByCode(storeCode);
            List<Map<String, Object>> insertList = new ArrayList<Map<String, Object>>();
            for (ModelTaskBean task : tasks) {
                Map<String, Object> insertMap = new HashMap<String, Object>();
                insertMap.put("taskId", task.getTaskId());
                insertMap.put("taskStatus", ModelConstant.TASK_RUN_STATUS_ING);
                insertMap.put("taskType", task.getTaskType());
                insertMap.put("disCode", store.getRegionCode());
                insertMap.put("disName", store.getRegionName());
                insertMap.put("orgCode", store.getSaleBranchCode());
                insertMap.put("orgName", store.getBranchName());
                insertMap.put("storeCode", store.getStoreCode());
                insertMap.put("storeName", store.getStoreName());
                insertMap.put("cateCode", baseInfo.getCateCode());
                insertMap.put("cateName", baseInfo.getCateName());
                insertMap.put("branch4code", baseInfo.getBranch4code());
                insertMap.put("branch9code", baseInfo.getBranch9code());
                insertMap.put("branchName", baseInfo.getBranchName());
                insertMap.put("storageCode", "1".equals(comm.getCounterFlag()) ? ModelBean.STORAGE_TYPE.COUNTER_TYPE
                        : ModelBean.STORAGE_TYPE.MODEL_TYPE);
                insertList.add(insertMap);
            }
            modelManageDaoService.batchInsertTaskAssign(insertList
                    .toArray(new HashMap[insertList.size()]));
        }
    }
    
    @Override
    @Transactional
    public ReturnMsg<CommonRtn> saveTask(List<String> storeList, List<BrandInfo> brandList,
            String startTime, String endTime, String storage, Integer taskType, String staffId,
            Long taskId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (CollectionUtils.isEmpty(storeList) || CollectionUtils.isEmpty(brandList)
                || !checkStr(startTime, endTime, storage) || taskType == null) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        List<String> brandCodeList = new ArrayList<String>();
        for (BrandInfo brand : brandList) {
            brandCodeList.add(brand.getBrandCode());
        }
        // 修改时判断任务是否未开始
        if (taskId != null && !modelManageDaoService.checkTaskIsUpdate(taskId)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E004, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        // 判断任务是否可以创建
        if (modelManageDaoService.checkTaskExist(storeList, brandCodeList, startTime, endTime
                + END_TIME_SUFFIXES, taskType, taskId,storage)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E002, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        ModelTaskMain task = new ModelTaskMain();
        task.setStartTime(DateUtils.getDateByStr(startTime, DATE_FORMAT));
        task.setEndTime(DateUtils.getDateByStr(endTime + END_TIME_SUFFIXES, FULL_DATE_FORMAT));
        task.setOprStaff(staffId);
        task.setOprTime(new Date());
        task.setStorageCode(storage);
        // 判断是新增还是修改
        if (taskId == null) {
            task.setTaskType(taskType);
            task.setRunStatus(ModelConstant.TASK_RUN_STATUS_BEFORE);
            task.setValidStatus(ModelConstant.TASK_VALID_STATUS_ENABLE);
            task.setCreateStatus(ModelConstant.TASK_CREATE_STATUS_N);
            // 插入任务主表，返回任务Id
            taskId = modelManageDaoService.insertTask(task);
        } else {
            // 更新任务主表
            modelManageDaoService.updateTaskMainByTaskId(task, taskId);
            // 查询任务下门店列表
            List<String> storeCodeList = modelManageDaoService.queryTaskStoreCodeList(taskId);
            List<String> storeCodeOld = new ArrayList<String>();
            storeCodeOld.addAll(storeCodeList);
            // 原门店列表移除修改选择的门店列表，剩下的需要删除
            storeCodeOld.removeAll(storeList);
            // 修改选择的门店列表移除原门店列表，剩下的需要新增
            storeList.removeAll(storeCodeList);
            if (CollectionUtils.isNotEmpty(storeCodeOld)) {
                modelManageDaoService.delteTaskStoreByStoreCode(storeCodeOld, taskId);
            }
            List<String> brand9CodeList = modelManageDaoService.queryTaskBrand9CodeList(taskId);
            List<String> brandCodeOld = new ArrayList<String>();
            brandCodeOld.addAll(brand9CodeList);
            // 原品牌列表移除修改选择的品牌列表，剩下的需要删除
            brandCodeOld.removeAll(brandCodeList);
            // 修改选择的品牌列表移除原品牌列表，剩下的需要新增
            brandCodeList.removeAll(brand9CodeList);
            if (CollectionUtils.isNotEmpty(brandCodeOld)) {
                modelManageDaoService.deleteTaskBrandByBrand9Code(brandCodeOld, taskId);
            }
            //更新任务下组织列表缓存
            redisClient.hdel(CacheKeyConstants.STORE_TREE,  String.format(CacheKeyConstants.MODEL_ORG_TREE_TASK, taskId));
        }
        batchInsertTaskStore(storeList, taskId);
        batchInsertTaskBrand(brandCodeList, taskId);
        return ret;
    }

    @SuppressWarnings("unchecked")
    private void batchInsertTaskStore(List<String> storeList, Long taskId) {
        if (CollectionUtils.isNotEmpty(storeList)) {
            // 查询门店详细信息
            List<StoreInfo> storeInfoList = storeInfoService.queryStoreByStoreCodes(storeList);
            if (CollectionUtils.isNotEmpty(storeInfoList)) {
                Map<String, Object>[] maps = new Map[storeInfoList.size()];
                int i = 0;
                for (StoreInfo store : storeInfoList) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("storeCode", store.getStoreCode());
                    map.put("orgCode", store.getSaleBranchCode());
                    map.put("disCode", store.getRegionCode());
                    map.put("orgName", store.getBranchName());
                    map.put("disName", store.getRegionName());
                    map.put("storeName", store.getStoreName());
                    map.put("taskId", taskId);
                    maps[i] = map;
                    i++;
                }
                // 批量插入任务门店范围表
                modelManageDaoService.batchInsertTaskStore(maps);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void batchInsertTaskBrand(List<String> brandCodeList, Long taskId) {
        if (CollectionUtils.isNotEmpty(brandCodeList)) {
            // 查询品牌详细信息
            List<ModelCategoryBrandInfoBean> brandInfo = modelManageDaoService
                    .queryBrandList(brandCodeList);
            if (CollectionUtils.isNotEmpty(brandInfo)) {
                Map<String, Object>[] brandMaps = new Map[brandInfo.size()];
                int j = 0;
                for (ModelCategoryBrandInfoBean brand : brandInfo) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("taskId", taskId);
                    map.put("cateCode", brand.getCateCode());
                    map.put("cateName", brand.getCateName());
                    map.put("branch4code", brand.getBranch4code());
                    map.put("branch9code", brand.getBranch9code());
                    map.put("branchName", brand.getBranchName());
                    map.put("taskId", taskId);
                    brandMaps[j] = map;
                    j++;
                }
                // 批量插入任务品牌范围表
                modelManageDaoService.batchInsertTaskBrand(brandMaps);
            }
        }
    }

    private boolean checkStr(String... strings) {
        for (String s : strings) {
            if (StringUtils.isBlank(s)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public ReturnMsg<TaskDetailBean> queryTaskDetail(Long taskId) {
        ReturnMsg<TaskDetailBean> ret = new ReturnMsg<TaskDetailBean>();
        if (taskId == null) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        ModelTaskMainBean modelDetailMain = modelManageDaoService.queryModelTaskDetail(taskId);
        if (modelDetailMain != null) {
            TaskDetailBean detail = new TaskDetailBean();
            // 查询任务下品类品牌列表
            List<BrandBean> brandList = modelManageDaoService.queryTaskBrandByTaskId(taskId);
            List<ModelCateBrand> cateBrandList = getModelCateBrandList(brandList);
            // 查询任务下门店编码列表
            List<String> storeCodeList = modelManageDaoService.queryTaskStoreCodeList(taskId);
            StoreInfo storeInfo = storeInfoService.queryStoreByCode(storeCodeList.get(0));
            if (storeInfo != null
                    && OrgTreeBean.STORE_TYPE.STORE_TYPE_SERVICE.equals(storeInfo
                            .getStoreTypeCode())) {
                detail.setStoreType(OrgTreeBean.STORE_TYPE.TYPE_SERVICE);
            } else {
                detail.setStoreType(OrgTreeBean.STORE_TYPE.TYPE_STORE);
            }
            detail.setTaskId(taskId);
            detail.setTaskType(modelDetailMain.getTaskType());
            detail.setStartTime(DateUtils.getDateStrByFormat(modelDetailMain.getStartTime(),
                    DATE_FORMAT));
            detail.setEndTime(DateUtils.getDateStrByFormat(modelDetailMain.getEndTime(),
                    DATE_FORMAT));
            detail.setStorage(modelDetailMain.getStorageCode());
            detail.setStoreCodeList(storeCodeList);
            detail.setCateBrandList(cateBrandList);
            ret.setData(detail);
        } else {
            ret.setError(ModelErrorConstant.MODEL_ERR_E003, ModelErrorConstant.MODEL_ERR_MAP);
        }
        return ret;
    }

    @Override
    public ReturnMsg<CommonRtn> validTask(Long taskId, Integer type) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (taskId == null || type == null) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        ModelTaskMain task = new ModelTaskMain();
        task.setValidStatus(type == 1 ? ModelConstant.TASK_VALID_STATUS_ENABLE
                : ModelConstant.TASK_VALID_STATUS_DISABLE);
        modelManageDaoService.updateTaskMainByTaskId(task, taskId);
        return ret;
    }

    @Transactional
    @Override
    public ReturnMsg<CommonRtn> deleteTask(Long taskId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (taskId == null) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        // 判断任务是否是未开始，只有未开始才可以删除
        if (!modelManageDaoService.checkTaskIsUpdate(taskId)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E005, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        // 删除任务主表，任务门店表，任务品牌表
        modelManageDaoService.deleteTaskByTaskId(taskId);
        modelManageDaoService.deleteTaskBrandById(taskId);
        modelManageDaoService.deleteTaskStoreById(taskId);
        return ret;
    }

    @Override
    public ReturnMsg<QueryClusterList> queryModelClusterList(String commInfo, Integer pageSize, Integer pageNo) {
        ReturnMsg<QueryClusterList> ret = new ReturnMsg<QueryClusterList>();
        QueryClusterList qr = new QueryClusterList();
        List<ModelCluster> list = new ArrayList<ModelCluster>();
        int count = modelManageDaoService.queryModelClusterCount(commInfo, false);
        int exportCount = count;
        // 查询详细商品数量，用于导出
        if (count > 0) {
            exportCount = modelManageDaoService.queryModelClusterCount(commInfo, true);
        }
        if (count > 0) {
            list = modelManageDaoService.queryModelClusterList(commInfo, pageNo, pageSize);
        }
        qr.setRecords(list);
        qr.setTotalSize(count);
        qr.setExportSize(exportCount);
        ret.setData(qr);
        return ret;
    }
    
    @Override
    public ReturnMsg<QueryClusterInfoList> queryModelClusterInfoList(String commInfo, Integer pageSize, Integer pageNo) {
        ReturnMsg<QueryClusterInfoList> ret = new ReturnMsg<QueryClusterInfoList>();
        QueryClusterInfoList qr = new QueryClusterInfoList();
     
        List<ModelClusterInfo> list = new ArrayList<ModelClusterInfo>();
        // 商品簇数量，导出数量
        int count = modelManageDaoService.queryModelClusterCount(commInfo, true);
        int exportCount = count;
        
        if (count > 0) {
            list = modelManageDaoService.queryModelClusterInfoList(commInfo, pageNo, pageSize);
        }
        qr.setRecords(list);
        qr.setTotalSize(count);
        qr.setExportSize(exportCount);
        ret.setData(qr);
        return ret;
    }

    /**
     * 查询未分配
     */
    @Override
    public ReturnMsg<QueryResult<ModelTaskNoAssignVo>> queryModelTaskNoAssign(String regionCode,
            String branchCode, String storeCode, int pageSize, int pageNo, Long taskId, String taskStatus, String cateCode) {
        ReturnMsg<QueryResult<ModelTaskNoAssignVo>> ret = new ReturnMsg<QueryResult<ModelTaskNoAssignVo>>();
        List<ModelTaskAssignDetailsBean> list = null;
        QueryResult<ModelTaskNoAssignVo> qr = new QueryResult<ModelTaskNoAssignVo>();
        //查询任务未分配
        int count = modelManageDaoService.queryTaskNoAssignCount(regionCode, branchCode, storeCode, cateCode,
                taskId);
        if (count > 0) {
            list = modelManageDaoService.queryTaskNoAssign(regionCode, branchCode, storeCode, cateCode,
                    pageSize, pageNo, taskId);
        }
        qr.setRecords(convertNoAssignList(list));
        qr.setTotalSize(count);
        ret.setData(qr);
        return ret;
    }
    
    /**
     * 转换未分配品类列表
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param list
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelTaskNoAssignVo> convertNoAssignList(List<ModelTaskAssignDetailsBean> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            ModelTaskNoAssignVo vo;
            List<ModelTaskNoAssignVo> voList = new ArrayList<ModelTaskNoAssignVo>();
            for (ModelTaskAssignDetailsBean bean : list) {
                vo = new ModelTaskNoAssignVo();
                vo.setTaskId(bean.getTaskId());
                vo.setRegionName(bean.getDisName());
                vo.setBranchName(bean.getOrgName());
                vo.setStoreName(bean.getStoreName());
                vo.setStoreCode(bean.getStoreCode());
                vo.setCategoryName(bean.getCateName());
                vo.setCateCode(bean.getCateCode());
                vo.setBrandNames(bean.getBranchName());
                // 判断是否是指定的督导
                if (StringUtils.isNotBlank(bean.getAcceptStaff())) {
                    vo.setAssignPerson(modelTaskNewService.queryStaffName(bean.getAcceptStaff()));
                } else {
                    // 查询品类下的督导
                    vo.setAssignPerson(modelTaskNewService.queryStaffName(bean.getStoreCode(), bean.getCateCode()));
                }
                vo.setStaffId(bean.getAcceptStaff());
                voList.add(vo);
            }
            return voList;
        }
        return Collections.emptyList();
    }
    
    /**
     * 查询已分配
     */
    @Override
    public ReturnMsg<QueryResult<ModelTaskHasAssignVo>> queryModelTaskHasAssign(String regionCode, String branchCode,
            String storeCode, int pageSize, int pageNo, Long taskId, String taskStatus, String cateCode, String brandCode) {
        List<ModelTaskAssignDetailsBean> list = null;
        int count = modelManageDaoService.queryTaskHasAssignCount(taskId, regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus);
        if (count > 0) {
            list = modelManageDaoService.queryTaskHasAssignList(taskId, regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus, pageSize, pageNo);
        }
        QueryResult<ModelTaskHasAssignVo> qr = new QueryResult<ModelTaskHasAssignVo>();
        qr.setRecords(convertHasAssignList(list));
        qr.setTotalSize(count);
        ReturnMsg<QueryResult<ModelTaskHasAssignVo>> ret = new ReturnMsg<QueryResult<ModelTaskHasAssignVo>>();
        ret.setData(qr);
        return ret;
    }
    
    @Override
    public ReturnMsg<QueryResult<ModelTaskAssignVo>> queryAssignAllList(String regionCode, String branchCode,
            String storeCode, int pageSize, int pageNo, Long taskId, String taskStatus, String assignStatus,
            String cateCode, String brandCode) {
        LOGGER.info("queryAssignAllList for "+regionCode+","+branchCode+","+storeCode+","+pageSize+","+pageNo
                +","+ taskId+","+taskStatus+","+assignStatus+","+cateCode+","+brandCode);
        List<ModelTaskAssignDetailsBean> list = null;
        int count = modelManageDaoService.queryTaskAssignAllCount(taskId, regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus,assignStatus);
        if (count > 0) {
            // 处理页码
            int start = pageSize * (pageNo - 1);
            if (start < 0) {
                start = 0;
            }
            list = modelManageDaoService.queryAssignAllList(taskId, regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus,assignStatus, pageSize, start);
        }
        QueryResult<ModelTaskAssignVo> qr = new QueryResult<ModelTaskAssignVo>();
        qr.setRecords(convertAssignList(list));
        qr.setTotalSize(count);
        ReturnMsg<QueryResult<ModelTaskAssignVo>> ret = new ReturnMsg<QueryResult<ModelTaskAssignVo>>();
        ret.setData(qr);
        return ret;
    
    }
    
    private List<ModelTaskAssignVo> convertAssignList(List<ModelTaskAssignDetailsBean> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            ModelTaskAssignVo vo;
            List<ModelTaskAssignVo> voList = new ArrayList<ModelTaskAssignVo>();
            for (ModelTaskAssignDetailsBean bean : list) {
                vo = new ModelTaskAssignVo();
                vo.setRegionName(bean.getDisName());
                vo.setBranchName(bean.getOrgName());
                vo.setStoreName(bean.getStoreName());
                vo.setCategoryName(bean.getCateName());
                vo.setBrandName(bean.getBranchName());
                vo.setInventoryStatus(null == bean.getCheckTaskStatus() ? "0" : bean.getCheckTaskStatus().toString());
                if (ModelConstant.TASK_ASSIGN_STATUS_NO.equals(bean.getAssignStatus())){
                    vo.setAssignPerson("--");
                    vo.setInventoryPerson("--");
                    vo.setInventoryTime("--");
                    vo.setAssignTime("--");
                }else{
                    // 设置盘点人
                    if (StringUtils.isNotBlank(bean.getAcceptStaff())) {
                        vo.setInventoryPerson(modelTaskNewService.queryStaffName(bean.getAcceptStaff()));
                    }
                    // 判断是否是指定的督导
                    if (StringUtils.isNotBlank(bean.getAssignStaff())) {
                        vo.setAssignPerson(modelTaskNewService.queryStaffName(bean.getAssignStaff()));
                    } else {
                        // 查询品类下的督导
                        vo.setAssignPerson(modelTaskNewService.queryStaffName(bean.getStoreCode(), bean.getCateCode()));
                    }
                    if(ModelConstant.CHECK_TASK_STATUS_NO.equals(bean.getCheckTaskStatus())){
                        vo.setInventoryTime("--");
                    }else{
                        vo.setInventoryTime(null == bean.getCheckTaskSubmitTime() ? "--" : DateUtils.getDateStrByFormat(bean.getCheckTaskSubmitTime(), "yyyy.MM.dd HH:mm:ss"));
                    }
                    vo.setAssignTime(null == bean.getAssignTime() ? "--" : DateUtils.getDateStrByFormat(bean.getAssignTime(), "yyyy.MM.dd HH:mm:ss"));
                }
                voList.add(vo);
            }
            return voList;
        }
        return Collections.emptyList();
    
    }

    /**
     * 转换已分配样机数据
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param list
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelTaskHasAssignVo> convertHasAssignList(List<ModelTaskAssignDetailsBean> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            ModelTaskHasAssignVo vo;
            List<ModelTaskHasAssignVo> voList = new ArrayList<ModelTaskHasAssignVo>();
            for (ModelTaskAssignDetailsBean bean : list) {
                vo = new ModelTaskHasAssignVo();
                vo.setRegionName(bean.getDisName());
                vo.setBranchName(bean.getOrgName());
                vo.setStoreName(bean.getStoreName());
                vo.setCategoryName(bean.getCateName());
                vo.setBrandName(bean.getBranchName());
                // 设置盘点人
                if (StringUtils.isNotBlank(bean.getAcceptStaff())) {
                    vo.setInventoryPerson(modelTaskNewService.queryStaffName(bean.getAcceptStaff()));
                }
                vo.setInventoryStatus(null == bean.getCheckTaskStatus() ? "0" : bean.getCheckTaskStatus().toString());
                vo.setInventoryTime(null == bean.getCheckTaskSubmitTime() ? "--" : DateUtils.getDateStrByFormat(bean.getCheckTaskSubmitTime(), "yyyy.MM.dd HH:mm:ss"));
                voList.add(vo);
            }
            return voList;
        }
        return Collections.emptyList();
    }

    @Override
    public ReturnMsg<QueryResult<ModelEffectiveness>> queryModelEffectList(String regionCode, String branchCode, 
            String storeCode,String brandCode,String categoryCode,String comRangeName, String comGroupName, 
            String commCode,Integer pageNo,Integer pageSize) {
        ReturnMsg<QueryResult<ModelEffectiveness>> ret = new ReturnMsg<QueryResult<ModelEffectiveness>>();
        if (StringUtils.isBlank(regionCode)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        QueryResult<ModelEffectiveness> qr = new QueryResult<ModelEffectiveness>();
        List<ModelEffectiveness> list = new ArrayList<ModelEffectiveness>();
        //查询样机有效性
        int count = modelManageDaoService.queryModelEffectCount(regionCode, branchCode, comRangeName, comGroupName, commCode, storeCode, brandCode, categoryCode);
        if (count > 0) {
            list = modelManageDaoService.queryModelEffectList(regionCode, branchCode, comRangeName,
                    comGroupName, commCode, storeCode, brandCode, categoryCode, pageNo, pageSize);
        }
        qr.setTotalSize(count);
        qr.setRecords(list);
        ret.setData(qr);
        return ret;
    }
    
    /**
     * 样机有效性列表
     */
    @Override
    public ReturnMsg<QueryResult<ModelEffectiveness>> queryModelEffectListEx(String regionCode, String branchCode, 
            String storeCode,String brandCode,String categoryCode,String comRangeName, String comGroupName, 
            String commCode, String month, String storeType, Integer pageNo, Integer pageSize) {
        ReturnMsg<QueryResult<ModelEffectiveness>> ret = new ReturnMsg<QueryResult<ModelEffectiveness>>();
        if (StringUtils.isBlank(regionCode)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        QueryResult<ModelEffectiveness> qr = new QueryResult<ModelEffectiveness>();
        List<ModelEffectiveness> list = new ArrayList<ModelEffectiveness>();
        // 查询样机有效性
        int count = modelManageDaoService.queryModelEffectCountEx(regionCode, branchCode, comRangeName, comGroupName,
                commCode, storeCode, brandCode, categoryCode, month, storeType);
        if (count > 0) {
            list = modelManageDaoService.queryModelEffectListEx(regionCode, branchCode, comRangeName, comGroupName,
                    commCode, storeCode, brandCode, categoryCode, pageNo, pageSize, month, storeType, null);
        }
        qr.setTotalSize(count);
        qr.setRecords(list);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<Integer> deleteModelCluster(Integer clusterId, String commCode,
            String branchCode) {
        ReturnMsg<Integer> ret = new ReturnMsg<Integer>();
        if (StringUtils.isBlank(branchCode) || (clusterId == null && StringUtils.isBlank(commCode))) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        int result = modelManageDaoService.deleteModelCluster(clusterId, commCode, branchCode);
        ret.setData(result);
        return ret;
    }

    @Override
    public ReturnMsg<QueryResult<CommInfoBean>> queryClusterComm(Integer clusterId,
            String commCode, String branchCode, Integer pageSize, Integer pageNo) {
        ReturnMsg<QueryResult<CommInfoBean>> ret = new ReturnMsg<QueryResult<CommInfoBean>>();
        if (StringUtils.isBlank(branchCode) || (clusterId == null && StringUtils.isBlank(commCode))) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        QueryResult<CommInfoBean> qr = new QueryResult<CommInfoBean>();
        List<CommInfoBean> list = new ArrayList<CommInfoBean>();
        int count = modelManageDaoService.queryClusterCommCount(clusterId, commCode, branchCode);
        if (count > 0) {
            list = modelManageDaoService.queryClusterCommList(clusterId, commCode, branchCode,
                    pageSize, pageNo);
        }
        qr.setRecords(list);
        qr.setTotalSize(count);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<List<ModelCommClusterVo>> queryRecommendComm(String commCode,String branchCode) {
        StoreManDto storeMan = new StoreManDto();
        storeMan.setBranchCode(branchCode);
        // 查询推荐簇商品
        return modelCommClusterService.queryRecommendModelCommClusters(storeMan, commCode);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public ReturnMsg saveClusterComm(String mainCommCode, String commCode, String branchCode,
            String staffId) {
        ReturnMsg ret = new ReturnMsg();
        if (!checkStr(mainCommCode, commCode, branchCode, staffId)) {
            ret.setError(ModelErrorConstant.MODEL_ERR_E001, ModelErrorConstant.MODEL_ERR_MAP);
            return ret;
        }
        List<StoreInfo> storeList = storeInfoService.queryStoresByBranchCode(branchCode,
                StoreInfo.ORG_TYPE.SALE_TYPE);
        ModelZoneInfo modelZone = new ModelZoneInfo();
        if (CollectionUtils.isNotEmpty(storeList)) {
            modelZone.setDisCode(storeList.get(0).getRegionCode());
            modelZone.setDisName(storeList.get(0).getRegionName());
            modelZone.setOrgName(storeList.get(0).getBranchName());
        }
        modelZone.setOrgCode(branchCode);
        ret = modelCommClusterService.addModelCommCluster(modelZone, mainCommCode, commCode);
        modelManageDaoService.deleteNoCluster(mainCommCode, commCode, branchCode);
        return ret;
    }

    /**
     * excel最大导出条数
     */
    public ReturnMsg<Integer> queryExcelMaxSize() {
        ReturnMsg<Integer> result = new ReturnMsg<Integer>();
        result.setData(this.getExcelMaxSize());
        return result;
    }

    /**
     * excel导出，获取最大条数
     */
    private Integer getExcelMaxSize() {
        // 默认两万
        String size = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_EXCEL_SIZE,
                String.valueOf("20000"));
        Integer result = Integer.valueOf(size);
        return result;
    }

    /**
     * 功能描述: <br>
     * 导出前调用，返回ture才允许调用
     */
    private boolean startExportExcel() {
        boolean result = false;
        // 默认同时5个导出工作-大促期间，可限制该功能，禁止导出
        String size = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_TASK_SIZE,
                String.valueOf("5"));
        String cacheKey = CacheKeyConstants.MODEL_MANAGE_EXPORT_TASK_NUM;
        Integer nowSize = cacheUtils.get(cacheKey, Integer.class);
        if (null == nowSize || (StringUtils.isNotBlank(size) && nowSize < Integer.valueOf(size))) {
            result = true;
            // 导出任务缓存中计数加1
            cacheUtils.incr(cacheKey);
        }
        if (!result) {
            LOGGER.error("样机管理-后台-导出-导出并行任务超出上限,目前上限值:" + nowSize);
        }
        return result;
    }

    /**
     * 功能描述: <br>
     * 导出后调用，若抛出异常，请务必调用该方法
     */
    @Override
    public void endExportExcel() {
        cacheUtils.decr(CacheKeyConstants.MODEL_MANAGE_EXPORT_TASK_NUM);
    }

    @Override
    public ReturnMsg<Integer> queryExptLimit() {
        ReturnMsg<Integer> ret = new ReturnMsg<Integer>();
        ret.setData(getExptLimit());
        return ret;
    }
    
    @Override
    public ReturnMsg<Integer> queryExptCSVLimit() {
        ReturnMsg<Integer> ret = new ReturnMsg<Integer>();
        ret.setData(getExptCSVLimit());
        return ret;
    }

    private int getExptLimit() {
        String limit = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_EXCEL_SIZE,
                ConfigConstants.DEFAULT_MODEL_MANAGE_EXPORT_EXCEL_SIZE);
        return Integer.valueOf(limit).intValue();
    }
    
    private int getExptCSVLimit() {
        String limit = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_CSV_SIZE,
                ConfigConstants.DEFAULT_MODEL_MANAGE_EXPORT_CSV_SIZE);
        return Integer.valueOf(limit).intValue();
    }

    @Override
    public Workbook exportUnassignTask(String branchCode, String storeCode, String regionCode, String cateCode,
            Long taskId, Integer index) {
        if (!startExportExcel()) {
            return null;
        }
        int pageSize = getExptLimit();
        List<ModelTaskAssignDetailsBean> list = modelManageDaoService.queryTaskNoAssign(regionCode,
                branchCode, storeCode, cateCode, pageSize, index, taskId);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "大区名称",  "分公司名称", "门店名称", "品类名称", "分配人", "未分配品牌" };
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelTaskAssignDetailsBean model : list) {
                String[] st = new String[11];
                st[0] = model.getDisName();
                st[1] = model.getOrgName();
                st[2] = model.getStoreName();
                st[3] = model.getCateName();
                // 判断是否是指定的督导
                if (StringUtils.isNotBlank(model.getAcceptStaff())) {
                    st[4] = modelTaskNewService.queryStaffName(model.getAcceptStaff());
                } else {
                    // 查询品类下的督导
                    st[4] = modelTaskNewService.queryStaffName(model.getStoreCode(), model.getCateCode());
                }
                st[5] = model.getBranchName();
                exptList.add(st);
            }
        }
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        endExportExcel();
        return workbook;
    }

    /**
     * 功能描述: <br>
     * 样机清单导出
     * 
     * @param storeCode
     * @param pageNo
     * @param out
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void exportExcelModelByStore(String regionCode, String branchCode, String commCode, String storeCode,
            Integer pageNo, OutputStream output) {
        if (this.startExportExcel()) {
            // List<ModelBean> list = modelManageDaoService.queryModelByStoreCode(storeCode, pageNo,
            // this.getExcelMaxSize());
            List<ModelBean> list = modelManageDaoService.queryModelBySearchField(regionCode, branchCode, commCode,
                    storeCode, pageNo, this.getExcelMaxSize());

            int[] colWidth = new int[] { ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_FIVE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_FIVE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_SIX};
            // 标题
            String[] headNames = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "品类编码", "品类名称",
                    "品牌编码", "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "样机数量", "状态", "更新时间" };
            // list转换-保留要插入到excel中的字段
            List<Object[]> objectList = null;
            objectList = Lists.newArrayList(Lists.transform(list, new Function<ModelBean, Object[]>() {
                @Override
                public Object[] apply(ModelBean input) {
                    Object[] result = new Object[ModelConstant.NUM_SEVENTEEN];
                    result[ModelConstant.NUM_ZERO] = input.getRegionCode();
                    result[ModelConstant.NUM_ONE] = input.getRegionName();
                    result[ModelConstant.NUM_TWO] = input.getBranchCode();
                    result[ModelConstant.NUM_THREE] = input.getBranchName();
                    result[ModelConstant.NUM_FOUR] = input.getStoreCode();
                    result[ModelConstant.NUM_FIVE] = input.getStoreName();
                    result[ModelConstant.NUM_SIX] = input.getCateCode();
                    result[ModelConstant.NUM_SEVEN] = input.getCategoryName();
                    result[ModelConstant.NUM_EIGHT] = input.getBrand4code();
                    result[ModelConstant.NUM_NINE] = input.getBrandName();
                    result[ModelConstant.NUM_TEN] = input.getCommCode();
                    result[ModelConstant.NUM_ELEVEN] = input.getCommName();
                    result[ModelConstant.NUM_TWELVE] = input.getStorage();
                    result[ModelConstant.NUM_THIRTEEN] = input.getModelProperty();
                    result[ModelConstant.NUM_FOURTEEN] = input.getModelCount();
                    result[ModelConstant.NUM_FIFTEEN] = input.getNewFlag() == 0 ? "老样机" : "新样机";
                    if (null != input.getUpdateTime()) {
                        result[ModelConstant.NUM_SIXTEEN] = DateUtils.getLongStr(input.getUpdateTime());
                    }
                    return result;
                }
            }));
            try {
                ExcelUtils.exportExcel(output, colWidth, headNames, objectList);
            } catch (IOException e) {
                LOGGER.error("样机清单导出exportExcelModelByStore异常", e);
            } finally {
                // 必须调用
                this.endExportExcel();
            }
        }
    }

    private String getStoreTypeName(String storeType) {
        if(StringUtils.isBlank(storeType)){
            return "";
        }
        return ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_INFOS_MAP.get(storeType);
    }
    /**
     * 功能描述: <br>
     * 样机异常列表导出
     * 
     * @param storeCode
     * @param pageNo
     * @param out
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Deprecated
    public void exportExcelModelExptByStore(String storeCode, Integer pageNo, OutputStream output) {
        if (this.startExportExcel()) {

            List<ModelExptBean> list = modelManageDaoService.queryModelExptByStoreCode(null, null, storeCode,
                    pageNo, this.getExcelMaxSize(), null);
            int[] colWidth = new int[] { ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_FIVE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE, ModelConstant.NUM_THREE,
                    ModelConstant.NUM_THREE, ModelConstant.NUM_THREE };
            // 标题
            String[] headNames = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称",
                    "品类编码", "品类名称", "品牌编码", "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "样机清单数量", "盘点结果",
                    "异常原因", "盘点日期", "盘点人员", "处理人", "处理日期", "审核人" };
            // list转换-保留要插入到excel中的字段
            List<Object[]> objectList = null;
            objectList = Lists.newArrayList(Lists.transform(list,
                    new Function<ModelExptBean, Object[]>() {
                        @Override
                        public Object[] apply(ModelExptBean input) {
                            Object[] result = new Object[ModelConstant.NUM_TWENTY_TWO];
                            result[ModelConstant.NUM_ZERO] = input.getRegionCode();
                            result[ModelConstant.NUM_ONE] = input.getRegionName();
                            result[ModelConstant.NUM_TWO] = input.getBranchCode();
                            result[ModelConstant.NUM_THREE] = input.getBranchName();
                            result[ModelConstant.NUM_FOUR] = input.getStoreCode();
                            result[ModelConstant.NUM_FIVE] = input.getStoreName();
                            result[ModelConstant.NUM_SIX] = input.getCateCode();
                            result[ModelConstant.NUM_SEVEN] = input.getCategoryName();
                            result[ModelConstant.NUM_EIGHT] = input.getBrand4code();
                            result[ModelConstant.NUM_NINE] = input.getBrandName();
                            result[ModelConstant.NUM_TEN] = input.getCommCode();
                            result[ModelConstant.NUM_ELEVEN] = input.getCommName();
                            result[ModelConstant.NUM_TWELVE] = input.getStorage();
                            result[ModelConstant.NUM_THIRTEEN] = input.getModelProperty();
                            result[ModelConstant.NUM_FOURTEEN] = input.getModelCount();
                            result[ModelConstant.NUM_FIFTEEN] = input.getCheckResult();
                            result[ModelConstant.NUM_SIXTEEN] = input.getReason();
                            result[ModelConstant.NUM_SEVENTEEN] = input.getCheckTime();
                            result[ModelConstant.NUM_EIGHTEEN] = input.getCheckMan();
                            result[ModelConstant.NUM_NINTEEN] = "system".equals(input.getOperateMan()) ? "系统" : input.getOperateMan();
                            result[ModelConstant.NUM_TWENTY] = input.getOperateTime();
                            result[ModelConstant.NUM_TWENTY_ONE] = "system".equals(input.getExamineMan()) ? "系统" : input.getExamineMan();
                            return result;
                        }
                    }));
            try {
                ExcelUtils.exportExcel(output, colWidth, headNames, objectList);
            } catch (IOException e) {
                LOGGER.error("样机异常列表导出exportExcelModelExptByStore异常", e);
            } finally {
                // 必须调用
                this.endExportExcel();
            }

        }
    }

    @Deprecated
    @Override
    public Workbook exportSaleModelExpt(String storeCode, Integer index,Integer isInStorage) {
      //判断是否达到导出上限
        if (!startExportExcel()) {
            return null;
        }
        int pageSize = getExptLimit();
        List<SaleModelExptBean> list = modelManageDaoService.querySaleModelExptByStoreCode(null, null,
                storeCode, index, pageSize,isInStorage, null);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "品类编码",
                "品类名称", "品牌编码", "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "盘点数量", "库存数量", "是否入库" };
        if (CollectionUtils.isNotEmpty(list)) {
            //list转String数组
            for (SaleModelExptBean saleModel : list) {
                String[] st = new String[17];
                st[0] = saleModel.getRegionCode();
                st[1] = saleModel.getRegionName();
                st[2] = saleModel.getBranchCode();
                st[3] = saleModel.getBranchName();
                st[4] = saleModel.getStoreCode();
                st[5] = saleModel.getStoreName();
                st[6] = saleModel.getCateCode();
                st[7] = saleModel.getCategoryName();
                st[8] = saleModel.getBrand4code();
                st[9] = saleModel.getBrandName();
                st[10] = saleModel.getCommCode();
                st[11] = saleModel.getCommName();
                st[12] = ModelConstant.getModelLibValue(saleModel.getStorage());
                st[13] = saleModel.getModelProperty();
                st[14] = getStr(saleModel.getModelCount());
                st[15] = getStr(saleModel.getStockCount());
                st[16] = ModelConstant.STORAGE_FLAG.get(saleModel.getIsInStorage()) == null ? ""
                        : ModelConstant.STORAGE_FLAG.get(saleModel.getIsInStorage());
                exptList.add(st);
            }
        }
        //创建excel workBook对象
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        return workbook;
    }

    @Override
    @Deprecated
    public Workbook exportModelEffect(String regionCode, String branchCode, String brandCode, 
            String categoryCode, String storeCode, String comRangeName, String comGroupName, 
            String commCode,Integer index) {
        //判断是否达到导出上限
        if (!startExportExcel()) {
            return null;
        }
        int pageSize = getExptLimit();
        List<ModelEffectiveness> list = modelManageDaoService.queryModelEffectList(regionCode, branchCode, comRangeName,
                comGroupName, commCode, storeCode, brandCode, categoryCode, index, pageSize);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[28];
        String[] mainTitle = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称",
                "门店类型", "品类编码", "品类名称", "品牌编码", "品牌名称", "商品编码", "商品名称", "商品组", "所属簇系列", "样机数量" };
        for (int i = 0; i < mainTitle.length; i++) {
            titles[i] = mainTitle[i];
        }
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -12);
        Map<Integer, Integer> postion = new HashMap<Integer, Integer>();
        for (int i = 16; i < 28; i++) {
            c.add(Calendar.MONTH, 1);
            StringBuilder sb = new StringBuilder();
            sb.append(DateUtils.getDateStrByFormat(c.getTime(), MONTH_FORMAT)).append("销量");
            titles[i] = sb.toString();
            postion.put(c.get(Calendar.MONTH) + 1, i);
        }
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelEffectiveness modelEffect : list) {
                String[] st = new String[28];
                st[0] = modelEffect.getRegionCode();
                st[1] = modelEffect.getRegionName();
                st[2] = modelEffect.getBranchCode();
                st[3] = modelEffect.getBranchName();
                st[4] = modelEffect.getStoreCode();
                st[5] = modelEffect.getStoreName();
                st[6] = ModelConstant.getTaskTypeStr(modelEffect.getStoreType());
                st[7] = modelEffect.getCateCode();
                st[8] = modelEffect.getCategoryName();
                st[9] = modelEffect.getBrand4code();
                st[10] = modelEffect.getBrandName();
                st[11] = modelEffect.getCommCode();
                st[12] = modelEffect.getCommName();
                st[13] = modelEffect.getComGroupName();
                st[14] = modelEffect.getComRangeName();
                st[15] = getStr(modelEffect.getModelCount());
                st[postion.get(1)] = getStr(modelEffect.getSaleCount1());
                st[postion.get(2)] = getStr(modelEffect.getSaleCount2());
                st[postion.get(3)] = getStr(modelEffect.getSaleCount3());
                st[postion.get(4)] = getStr(modelEffect.getSaleCount4());
                st[postion.get(5)] = getStr(modelEffect.getSaleCount5());
                st[postion.get(6)] = getStr(modelEffect.getSaleCount6());
                st[postion.get(7)] = getStr(modelEffect.getSaleCount7());
                st[postion.get(8)] = getStr(modelEffect.getSaleCount8());
                st[postion.get(9)] = getStr(modelEffect.getSaleCount9());
                st[postion.get(10)] = getStr(modelEffect.getSaleCount10());
                st[postion.get(11)] = getStr(modelEffect.getSaleCount11());
                st[postion.get(12)] = getStr(modelEffect.getSaleCount12());
                exptList.add(st);
            }
        }
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        return workbook;
    }

    private String getStr(Integer o) {
        if (o != null) {
            return String.valueOf(o);
        }
        return "";
    }

    @Override
    public Workbook exportCommCluster(String branchCode, String commInfo, Integer isCluster, Integer index) {
        if (!startExportExcel()) {
            return null;
        }
        int pageSize = getExptLimit();
        List<ModelClusterInfo> list = modelManageDaoService.queryModelClusterDetailList(branchCode, commInfo,
                isCluster, index, pageSize);
        String[] titles = new String[] { "商品编码", "商品名称", "商品系列编码", "商品系列名称", "商品组代码", "商品组名称", "品牌编码", "品牌名称",
                "品牌9位编码", "品类编码", "品类名称" };
        List<String[]> exptList = new ArrayList<String[]>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelClusterInfo cluster : list) {
                String[] st = new String[11];
                st[0] = cluster.getCommCode();
                st[1] = cluster.getCommName();
                st[2] = getStr(cluster.getClusterId());
                st[3] = cluster.getComRangeName();
                st[4] = cluster.getComGroupCode();
                st[5] = cluster.getComGroupName();
                st[6] = cluster.getBrand4code();
                st[7] = cluster.getBrandName();
                st[8] = cluster.getBrand9code();
                st[9] = cluster.getCateCode();
                st[10] = cluster.getCategoryName();
                exptList.add(st);
            }
        }
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        return workbook;
    }

    /**
     * 查询任务品类品牌
     */
    @Override
    public List<ModelCateBrand> queryTaskCateBrands(Long taskId) {
        // 查询品类品牌列表
        List<BrandBean> list = modelManageDaoService.queryTaskCateBrands(taskId);
        if (CollectionUtils.isNotEmpty(list)) {
            ModelCateBrand vo;
            BrandBean brand;
            Map<String, ModelCateBrand> result = new HashMap<String, ModelCateBrand>();
            for (BrandBean bean : list) {
                vo = result.get(bean.getCategoryCode());
                if (null == vo) {
                    vo = new ModelCateBrand();
                    vo.setBrandList(new ArrayList<BrandBean>());
                }
                vo.setCategoryName(bean.getCategoryName());
                vo.setCategoryCode(bean.getCategoryCode());
                brand = new BrandBean();
                brand.setBrandCode(bean.getBrandCode());
                brand.setBrandName(bean.getBrandName());
                vo.getBrandList().add(brand);
                result.put(bean.getCategoryCode(), vo);
            }
            return new ArrayList<ModelCateBrand>(result.values());
        }
        return Collections.emptyList();
    }

    /**
     * 导出已分配任务列表
     */
    @Override
    public Workbook exportHasAssignTask(Long taskId, String regionCode, String branchCode, String storeCode,
            String cateCode, String brandCode, String taskStatus, Integer index) {
        if (!startExportExcel()) {
            return null;
        }
        int pageSize = getExptLimit();
        List<ModelTaskAssignDetailsBean> list = modelManageDaoService.queryTaskHasAssignList(taskId, 
                regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus, pageSize, index);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "大区名称",  "分公司名称", "门店名称", "品类名称", "品牌名称", "盘点人",
                "盘点状态", "盘点时间" };
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelTaskAssignDetailsBean model : list) {
                String[] st = new String[11];
                st[0] = model.getDisName();
                st[1] = model.getOrgName();
                st[2] = model.getStoreName();
                st[3] = model.getCateName();
                st[4] = model.getBranchName();
                st[5] = model.getAcceptStaff();
                if (StringUtils.isNotBlank(model.getAcceptStaff())) {
                    st[5] = modelTaskNewService.queryStaffName(model.getAcceptStaff());
                } else {
                    st[5] = "";
                }
                st[6] = (null == model.getCheckTaskStatus() ||  model.getCheckTaskStatus().intValue() == 0)? "未盘点" : "已提交";
                st[7] = null == model.getCheckTaskSubmitTime() ? "--" : DateUtils.getDateStrByFormat(model.getCheckTaskSubmitTime(), "yyyy.MM.dd HH:mm:ss");
                exptList.add(st);
            }
        }
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        endExportExcel();
        return workbook;
    }

    @Override
    public ReturnMsg<QueryResult<ModelTaskNoAssignVo>> queryAppointTask(String staffId, int currIndex, int pageSize) {
        ReturnMsg<QueryResult<ModelTaskNoAssignVo>> ret = new ReturnMsg<QueryResult<ModelTaskNoAssignVo>>();
        List<ModelTaskAssignDetailsBean> list = null;
        QueryResult<ModelTaskNoAssignVo> qr = new QueryResult<ModelTaskNoAssignVo>();
        //查询任务未分配
        int count = modelManageDaoService.queryAppointTaskTotal(staffId);
        if (count > 0) {
            list = modelManageDaoService.queryAppointTaskPage(staffId, currIndex, pageSize);
        }
        qr.setRecords(convertNoAssignList(list));
        qr.setTotalSize(count);
        ret.setData(qr);
        return ret;
    }

    /**
     * 清除指定督导任务
     */
    @Override
    public void clearAppointTask(Long taskId, String staffId, String storeCode, String cateCode) {
        modelManageDaoService.clearAppointTask(taskId, staffId, storeCode, cateCode);
    }

    /**
     * 导入商品簇信息
     */
    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public ReturnMsg<List<String>> batchImportClusterExcel(MultipartFile file) {

        MainPushExcelHandle excelHandle = new MainPushExcelHandle(file);
        // 获取所有的单元格
        List<Sheet> sheetList = excelHandle.getSheetsFromWorkbook();

        // 封装好的读取excel操作，返回List>,外围List为行，里面List为列
        List<List<String>> clusterList = excelHandle.getExcelContentFromSheet(sheetList.get(0), 1, -1);
        
        ReturnMsg<List<String>> returnMsg = new ReturnMsg<List<String>>();

        // 调用接口获取商品编码对应的品牌9位编码
        Map<String, String> brand9CodeMap = batchQueryBrand9Code(clusterList);

        // 文件内容校验
        List<String> errorLineList = valiExcelData(clusterList, brand9CodeMap);
        if (!CollectionUtils.isEmpty(errorLineList)) {
            LOGGER.error("valiExcelData. errorLineList: " + errorLineList);
            if (errorLineList.size() > 3) {
                errorLineList = errorLineList.subList(0, 3);
                errorLineList.add("...");
            }
            returnMsg.setData(errorLineList);
            returnMsg.setRetFlag(ReturnMsg.FAIL);
        } else {
            // 根据商品系列名称生成簇ID
            Map<String, Integer> clusterIdMap = generateClusterId(clusterList);
            // 所有簇商品信息
            List<ModelClusterInfo> clusterInfoList = parseClusterData(clusterList, clusterIdMap, brand9CodeMap);
            
            // 从redis中获取时间，若不是当天时间，则执行清空表(MODEL_COMMODITY_CLUSTER)操作
            if (needClearClusterByRedis()) {
                modelManageDaoService.clearModelCluster();
            }

            // 循环插入数据
            int batchSaveNum = 1000;
            int flagNum = 0;
            List<ModelClusterInfo> saveClusterInfoList = new ArrayList<ModelClusterInfo>();
            for (int i = 0; i < clusterInfoList.size(); i++) {
                if (flagNum < batchSaveNum) {
                    if (null != clusterInfoList.get(i)) {
                        saveClusterInfoList.add(clusterInfoList.get(i));
                        flagNum++;
                    }
                }
                if (flagNum >= batchSaveNum || i == (clusterInfoList.size() - 1)) {
                    // 执行保存操作
                    Map<String, Object>[] params = new Map[saveClusterInfoList.size()];
                    int j = 0;
                    for (ModelClusterInfo info : saveClusterInfoList) {
                        params[j] = BeanUtil.describe(info);
                        j++;
                    }
                    modelManageDaoService.batchSaveCluster(params);

                    // 重置调用条件
                    flagNum = 0;
                    saveClusterInfoList = new ArrayList<ModelClusterInfo>();
                }

            }
            // 更新redis中的时间
            updateImportClusterTimeOfRedis();
        }

        return returnMsg;

    }

    /**
     * 
     * 功能描述: 更新redis中的导入时间<br>
     * 〈功能详细描述〉
     *
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void updateImportClusterTimeOfRedis() {
        redisClient.set(CacheKeyConstants.MODEL_CLUSTER_IMPORT_TIME,
                DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_DATE_PATTERN));
        redisClient.expire(CacheKeyConstants.MODEL_CLUSTER_IMPORT_TIME, CacheKeyConstants.MODEL_CLUSTER_IMPORT_TIME_EXPIRE);
        LOGGER.info("updateImportClusterTimeOfRedis.");
    }

    /**
     * 
     * 功能描述:从redis中获取时间，判断是否需要清空商品簇表 <br>
     * 〈功能详细描述〉redis中获取时间不是今天、或者为空，则清空，返回true
     *
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private boolean needClearClusterByRedis() {
        boolean clearFlag = false;
        String value = redisClient.get(CacheKeyConstants.MODEL_CLUSTER_IMPORT_TIME);
        String nowDateStr = DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_DATE_PATTERN);
        if (!nowDateStr.equals(value)) {
            clearFlag = true;
        }
        LOGGER.info("needClearClusterByRedis. clear cluster table data, clearFlag: " + clearFlag);
        return clearFlag;
    }
    
    /**
     * 
     * 功能描述:根据商品系列名称生成簇ID <br>
     * 〈功能详细描述〉
     *
     * @param clusterList
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private Map<String, Integer> generateClusterId(List<List<String>> clusterList) {
        Map<String, Integer> clusterIdMap = new HashMap<String, Integer>();

        // 从数据库获取已有的商品系列名称对应的簇编码
        List<ModelClusterInfo> list = modelManageDaoService.queryClusterRangeNameClusterCode();
        for (ModelClusterInfo info : list) {
            if (StringUtils.isNotBlank(info.getComRangeName()) && null != info.getClusterId())
                clusterIdMap.put(info.getComRangeName(), info.getClusterId());
        }

        for (List<String> rowData : clusterList) {
            if (CollectionUtils.isNotEmpty(rowData) && ModelConstant.NUM_SEVEN == rowData.size()) {
                String comRangeName = rowData.get(ModelConstant.NUM_ONE);
                if (StringUtils.isNotBlank(comRangeName) && !clusterIdMap.containsKey(comRangeName)) {
                    String clusterId = sequenceSerivce.incrSequenceNumber(SEQUENCE_CLUSTER_CODE_KEY);
                    clusterIdMap.put(comRangeName, Integer.valueOf(clusterId));
                }
            }
        }
        return clusterIdMap;
    }

    /**
     * 
     * 根据商品编码批量获取品牌9位编码<br>
     * 〈功能详细描述〉
     *
     * @param clusterList
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private Map<String, String> batchQueryBrand9Code(List<List<String>> clusterList) {
        Map<String, String> brand9CodeMap = new HashMap<String, String>();
        if (CollectionUtils.isEmpty(clusterList)) {
            return brand9CodeMap;
        }
        // 每次批量查询20条(最多不能超过50)
        int batchQueryNum = 20;
        int flagNum = 0;
        List<RsfRequestDto> reqList = new ArrayList<RsfRequestDto>();
        
        for (int i = 0; i < clusterList.size(); i++) {
            if (flagNum < batchQueryNum) {
                if (CollectionUtils.isNotEmpty(clusterList.get(i))
                        || ModelConstant.NUM_SEVEN == clusterList.get(i).size()) {
                    String commCode = clusterList.get(i).get(0);
                    if (StringUtils.isNotBlank(commCode)) {
                        RsfRequestDto dto = new RsfRequestDto();
                        dto.setReqVal(commCode);
                        reqList.add(dto);
                        flagNum++;
                    }
                }
            }
            if (flagNum >= batchQueryNum || i == (clusterList.size() - 1)) {
                // 调用商品中心接口
                RsfListRequestDto requestDto = new RsfListRequestDto();
                requestDto.setReqList(reqList);
                
                RsfItemInfoListResponseDto rsp = productService.batchQueryProductBD(requestDto);
                if (rsp != null && SUCCESS.equals(rsp.getErrCode())) {
                    List<RsfItemInfoResponseDto> infoList = rsp.getItemInfoList();
                    if (CollectionUtils.isNotEmpty(infoList)) {
                        for (RsfItemInfoResponseDto info : infoList) {
                            if (StringUtils.isNotBlank(info.getPartNumber())
                                    && StringUtils.isNotBlank(info.getBrandId())) {
                                // 商品编码9、11位。000000000120875490 -> 去除前面的0
                                brand9CodeMap.put(info.getPartNumber().replaceAll("^(0+)", ""), info.getBrandId());
                            }
                        }
                    }
                } else {
                    LOGGER.error("batchQueryBrand9Code.Error Rsp: " + (rsp == null ? "is null" : rsp.getErrCode()));
                }
                // 重置调用条件
                flagNum = 0;
                reqList = new ArrayList<RsfRequestDto>();
            }
        }

        return brand9CodeMap;
    }
    
    private List<ModelClusterInfo> parseClusterData(List<List<String>> clusterList, Map<String, Integer> clusterIdMap,
            Map<String, String> brand9CodeMap) {
        List<ModelClusterInfo> clusterInfoList = new ArrayList<ModelClusterInfo>();
        Map<String, ModelClusterInfo> clusterMap = new HashMap<String, ModelClusterInfo>();
        for (List<String> lineData : clusterList) {
            if (StringUtils.isBlank(lineData.get(0)) && StringUtils.isBlank(lineData.get(1)) 
                    && StringUtils.isBlank(lineData.get(2)) && StringUtils.isBlank(lineData.get(3)) 
                    && StringUtils.isBlank(lineData.get(4)) && StringUtils.isBlank(lineData.get(5)) 
                    && StringUtils.isBlank(lineData.get(6))) {
                continue;
            }
            ModelClusterInfo info = new ModelClusterInfo();
            info.setCommCode(lineData.get(0));
            info.setComRangeName(lineData.get(1));
            info.setComGroupCode(lineData.get(2));
            info.setComGroupName(lineData.get(3));
            info.setBrand4code(lineData.get(4));
            info.setBrandName(lineData.get(5));
            info.setCommName(lineData.get(6));
            // 品类编码(取9位品牌编码的前5位)
            info.setCateCode(brand9CodeMap.get(info.getCommCode()).substring(0, 5));
            info.setCategoryName(ModelConstant.COMM_CATE_INFOS.get(info.getCateCode()));
            info.setBrand9code(brand9CodeMap.get(info.getCommCode()));
            info.setClusterId(clusterIdMap.get(info.getComRangeName()));
            info.setDatetime(new Date());
            clusterMap.put(info.getCommCode(), info);
        }
        for (String key : clusterMap.keySet()) {
            clusterInfoList.add(clusterMap.get(key));
        }
        return clusterInfoList;
    }

    /**'
     * 
     * 校验Excel导入文件数据
     *
     * @param clusterList
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<String> valiExcelData(List<List<String>> clusterList, Map<String, String> brand9CodeMap) {
        List<String> errorList = new ArrayList<String>();

        if (CollectionUtils.isEmpty(clusterList)) {
            errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_000)));
            return errorList;
        }
        
        // 超过20000条数据，则提示先拆分再导入
        if (clusterList.size() > IMPORT_EXCEL_DATA_LIMT) {
        	errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_015)));
            return errorList;
        }

        String rowNum = null;
        // 列数
        int colNum = 7;
        for (int i = 0; i < clusterList.size(); i++) {
            rowNum = "第" + (i + 2) + "行 ";
            // 校验行数据是否完整
            List<String> lineData = clusterList.get(i);
            if (CollectionUtils.isEmpty(lineData)) {
                errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_001), rowNum));
            } else if (lineData.size() != colNum) {
                errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_002), rowNum, colNum));
            } else {
                // 列数据校验
                // 商品编码
                String commCode = lineData.get(0);
                // 商品系列名称
                String comRangeName = lineData.get(1);
                // 商品组代码
                String comGroupCode = lineData.get(2);
                // 商品组名称
                String comGroupName = lineData.get(3);
                // 品牌4位编码
                String brand4code = lineData.get(4);
                // 品牌名称
                String brandName = lineData.get(5);
                // 商品名称
                String commName = lineData.get(6);
                // 异常行，直接跳过
                if (StringUtils.isBlank(commCode) && StringUtils.isBlank(comRangeName) 
                        && StringUtils.isBlank(comGroupCode) && StringUtils.isBlank(comGroupName) 
                        && StringUtils.isBlank(brand4code) && StringUtils.isBlank(brandName) 
                        && StringUtils.isBlank(commName)) {
                    continue;
                }

                if (StringUtils.isBlank(commCode)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_008), rowNum));
                } else {
                    // 品牌9位编码(需要调用商品中心接口查询)
                    String brand9code = brand9CodeMap.get(commCode);
                    
                    if (StringUtils.isBlank(brand9code)) {
                        errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_006), rowNum));
                    } else {
                        if (ModelConstant.NUM_NINE == brand9code.length()) {
                            // 品类编码(取9位品牌编码的前5位)
                            String cateCode = brand9code.substring(0, 5);
                            // 品类名称(Map中取值，取不到值error)
                            String categoryName = ModelConstant.COMM_CATE_INFOS.get(cateCode);
                            if (StringUtils.isBlank(categoryName)) {
                                LOGGER.error("valiExcelData. CateCode&categoryName not match! CateCode: " + cateCode);
                                errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_004),
                                        rowNum));
                            }
                        } else {
                            errorList.add(String
                                    .format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_014), rowNum));
                        }
                    }
                }
                if (StringUtils.isBlank(comRangeName)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_011), rowNum));
                }
                if (StringUtils.isBlank(comGroupCode)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_012), rowNum));
                }
                if (StringUtils.isBlank(comGroupName)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_013), rowNum));
                }
                if (StringUtils.isBlank(brand4code)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_005), rowNum));
                }
                if (StringUtils.isBlank(brandName)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_007), rowNum));
                }
                if (StringUtils.isBlank(commName)) {
                    errorList.add(String.format(getErrorMsg(ModelClusterErrorConstants.CLUSTER_ERR_009), rowNum));
                }
            }
        }
        return errorList;
    }
    
    private String getErrorMsg(String errorCode) {
        return ModelClusterErrorConstants.MODEL_CLUSTER_ERR_MAP.get(errorCode);
    }

    /**
     * 清空商品簇表信息
     */
    @Override
    public void clearCluster() {
        modelManageDaoService.clearModelCluster();
    }

    /**
     * 是否超过样机清单导出的上限
     */
    @Override
    public boolean overExportModelTimes() {
        boolean overFlag = false;
        // 上次导出时间
        String lastExportDate = redisClient.hget(CacheKeyConstants.MODEL_EXPORT_LIMIT,
                CacheKeyConstants.MODEL_EXPORT_LIMIT_TIME);
        String nowDateStr = DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_DATE_PATTERN);
        // 无数据或者不是今天，重置redis数据
        if (!nowDateStr.equals(lastExportDate)) {
            redisClient.hset(CacheKeyConstants.MODEL_EXPORT_LIMIT, CacheKeyConstants.MODEL_EXPORT_LIMIT_TIME,
                    nowDateStr);
            redisClient.hset(CacheKeyConstants.MODEL_EXPORT_LIMIT, CacheKeyConstants.MODEL_EXPORT_LIMIT_NUM,
                    String.valueOf(ModelConstant.NUM_ZERO));
            redisClient.expireAt(CacheKeyConstants.MODEL_EXPORT_LIMIT, redisExpireTime());
        } else {
            // 是今天，判断次数是否超限
            String todayExportNumStr = redisClient.hget(CacheKeyConstants.MODEL_EXPORT_LIMIT,
                    CacheKeyConstants.MODEL_EXPORT_LIMIT_NUM);
            int todayExportNum = 0;
            try {
                todayExportNum = Integer.parseInt(todayExportNumStr);
            } catch (NumberFormatException e) {
                LOGGER.error("overExportModelTimes. todayExportNum:" + todayExportNumStr, e);
            }
            if (todayExportNum >= EXPORT_MODEL_TIMES_LIMIT) {
                overFlag = true;
            }
        }
        return overFlag;
    }
    
    private long redisExpireTime() {
        // 取当前时间的小时数和分钟数
        Date tomorrowZeroPoint = DateUtils.getNextDay(DateUtils.getNowZeroPoint(), 1);
        return tomorrowZeroPoint.getTime() / 1000;
    }

    /**
     * 样机清单导出次数+1
     */
    @Override
    public void addExportModelTime() {
        String nowDateStr = DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_DATE_PATTERN);
        String todayExportNumStr = redisClient.hget(CacheKeyConstants.MODEL_EXPORT_LIMIT,
                CacheKeyConstants.MODEL_EXPORT_LIMIT_NUM);
        int todayExportNum = 0;
        try {
            todayExportNum = Integer.parseInt(todayExportNumStr);
        } catch (NumberFormatException e) {
            LOGGER.error("overExportModelTimes. todayExportNum:" + todayExportNumStr, e);
        }
        redisClient.hset(CacheKeyConstants.MODEL_EXPORT_LIMIT, CacheKeyConstants.MODEL_EXPORT_LIMIT_TIME, nowDateStr);
        redisClient.hset(CacheKeyConstants.MODEL_EXPORT_LIMIT, CacheKeyConstants.MODEL_EXPORT_LIMIT_NUM,
                String.valueOf(++todayExportNum));
//        redisClient.expire(CacheKeyConstants.MODEL_EXPORT_LIMIT, CacheKeyConstants.ONE_DAY_EXPIRE_TIME);
    }

    @Override
    public void exportExcelModelByStoreEx(String staffId, String regionCode, String branchCode, String commCode, String storeCode,
 Integer pageNo, String status, String categoryCode, String brandCode) {
        LOGGER.info(
                "exportExcelModelByStoreEx.staffId:{}, regionCode:{}, branchCode:{}, commCode:{}, storeCode:{}, pageNo：{}, status:{},categoryCode:{},brandCode:{}",
                new Object[] { staffId, regionCode, branchCode, commCode, storeCode, pageNo, status, categoryCode,
                        brandCode });

        List<ModelBean> list = modelManageDaoService.queryModelBySearchField(regionCode, branchCode, commCode,
                storeCode, pageNo, this.getExptCSVLimit(), status, categoryCode, brandCode);
        // 标题
        String[] headNames = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "品类编码", "品类名称", "品牌编码",
                "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "样机数量", "状态", "更新时间", "门店类型" };
        List<List<String>> data = null;
        if (CollectionUtils.isNotEmpty(list)) {
            // list转换-保留要插入到csv中的字段
            data = com.google.common.collect.Lists.transform(list, new Function<ModelBean, List<String>>() {
                @Override
                public List<String> apply(ModelBean bean) {
                    List<String> msg = new ArrayList<String>();
                    msg.add(bean.getRegionCode());
                    msg.add(bean.getRegionName());
                    msg.add(bean.getBranchCode());
                    msg.add(bean.getBranchName());
                    msg.add(bean.getStoreCode());
                    msg.add(bean.getStoreName());
                    msg.add(bean.getCateCode());
                    msg.add(bean.getCategoryName());
                    msg.add(bean.getBrand4code());
                    msg.add(bean.getBrandName());
                    msg.add(bean.getCommCode());
                    msg.add(bean.getCommName());
                    msg.add(bean.getStorage());
                    msg.add(bean.getModelProperty());
                    msg.add(String.valueOf(bean.getModelCount()));
                    msg.add(bean.getNewFlag() == 0 ? "老样机" : "新样机");
                    if (null != bean.getUpdateTime()) {
                        msg.add(DateUtils.getLongStr(bean.getUpdateTime()));
                    }
                    msg.add(getStoreTypeName(bean.getStoreType()));
                    return msg;
                }
            });
        }
        try {
            String fileName = "modelList_" + pageNo;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, headNames, data, "样机清单" + pageNo,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportExcelModelByStoreEx failed.", e);
        }
    }

    @Override
    public void exportCommClusterEx(String staffId, String branchCode, String commInfo, Integer isCluster, Integer index) {
        int pageSize = getExptLimit();
        LOGGER.info("exportCommClusterEx.staffId:{}, branchCode:{}, commInfo:{}, isCluster:{}, index:{}", new Object[] {
                staffId, branchCode, commInfo, isCluster, index });
        List<ModelClusterInfo> list = modelManageDaoService.queryModelClusterDetailList(branchCode, commInfo,
                isCluster, index, pageSize);
        String[] titles = new String[] { "商品编码", "商品名称", "商品系列编码", "商品系列名称", "商品组代码", "商品组名称", "品牌编码", "品牌名称",
                "品牌9位编码", "品类编码", "品类名称" };
        if (CollectionUtils.isEmpty(list)) {
            LOGGER.error("exportCommClusterEx failed. List is null");
            return;
        }
        // list转换-保留要插入到csv中的字段
        List<List<String>> data = com.google.common.collect.Lists.transform(list,
                new Function<ModelClusterInfo, List<String>>() {
                    @Override
                    public List<String> apply(ModelClusterInfo cluster) {
                        List<String> msg = new ArrayList<String>();
                        msg.add(cluster.getCommCode());
                        msg.add(cluster.getCommName());
                        msg.add(getStr(cluster.getClusterId()));
                        msg.add(cluster.getComRangeName());
                        msg.add(cluster.getComGroupCode());
                        msg.add(cluster.getComGroupName());
                        msg.add(cluster.getBrand4code());
                        msg.add(cluster.getBrandName());
                        msg.add(cluster.getBrand9code());
                        msg.add(cluster.getCateCode());
                        msg.add(cluster.getCategoryName());
                        return msg;
                    }
                });
        try {
            String fileName = "modelCluster-" + index;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "商品簇" + index,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportCommClusterEx failed", e);
        }
    }
    
    /**
     * 导出样机异常CSV文件
     */
    @Override
    public void exportExcelModelExptByStoreEx(String staffId, String regionCode, String branchCode, String storeCode,
            Integer pageNo) {
        LOGGER.info("exportExcelModelExptByStoreEx. staffId:{}, regionCode:{}, branchCode:{}, storeCode:{}, pageNo:{}",
                new Object[] { staffId, regionCode, branchCode, storeCode, pageNo });
        List<ModelExptBean> list = modelManageDaoService.queryModelExptByStoreCode(regionCode, branchCode, storeCode,
                pageNo, this.getExptCSVLimit(), EXPORT_SEARCH);
        // 标题
        String[] headNames = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "门店类型", "品类编码", "品类名称",
                "品牌编码", "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "样机清单数量", "盘点结果", "异常原因", "盘点日期", "盘点人员", "处理人", "处理日期",
                "审核人" };

        // list转换-保留要插入到csv中的字段
        List<List<String>> data = com.google.common.collect.Lists.transform(list,
                new Function<ModelExptBean, List<String>>() {
                    @Override
                    public List<String> apply(ModelExptBean input) {
                        List<String> msg = new ArrayList<String>();
                        msg.add(input.getRegionCode());
                        msg.add(input.getRegionName());
                        msg.add(input.getBranchCode());
                        msg.add(input.getBranchName());
                        msg.add(input.getStoreCode());
                        msg.add(input.getStoreName());
                        String storeTypeName = "";
                        if (StringUtils.isNotBlank(input.getStoreType())) {
                            storeTypeName = ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_INFOS_MAP.get(input
                                    .getStoreType());
                        }
                        msg.add(storeTypeName);
                        msg.add(input.getCateCode());
                        msg.add(input.getCategoryName());
                        msg.add(input.getBrand4code());
                        msg.add(input.getBrandName());
                        msg.add(input.getCommCode());
                        msg.add(input.getCommName());
                        msg.add(input.getStorage());
                        msg.add(input.getModelProperty());
                        msg.add(input.getModelCount() == null ? "0" : String.valueOf(input.getModelCount()));
                        msg.add(input.getCheckResult());
                        msg.add(input.getReason());
                        msg.add(input.getCheckTime());
                        msg.add(input.getCheckMan());
                        msg.add("system".equals(input.getOperateMan()) ? "系统" : input.getOperateMan());
                        msg.add(input.getOperateTime());
                        msg.add("system".equals(input.getExamineMan()) ? "系统" : input.getExamineMan());
                        return msg;
                    }
                });

        try {
            String fileName = "probModelList-" + regionCode + "-" + pageNo;

            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, headNames, data, "异常样机清单" + pageNo,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("样机异常列表导出exportExcelModelExptByStore异常", e);
        } finally {
        }
    }
    
    /**
     * 导出已分配任务列表
     */
    @Override
    public void exportHasAssignTaskEx(String staffId, Long taskId, String regionCode, String branchCode, String storeCode,
            String cateCode, String brandCode, String taskStatus, Integer index) {
        int pageSize = getExptLimit();
        List<ModelTaskAssignDetailsBean> list = modelManageDaoService.queryTaskHasAssignList(taskId, 
                regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus, pageSize, index);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "大区名称",  "分公司名称", "门店名称", "品类名称", "品牌名称", "盘点人",
                "盘点状态", "盘点时间" };
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelTaskAssignDetailsBean model : list) {
                String[] st = new String[11];
                st[0] = model.getDisName();
                st[1] = model.getOrgName();
                st[2] = model.getStoreName();
                st[3] = model.getCateName();
                st[4] = model.getBranchName();
                st[5] = model.getAcceptStaff();
                if (StringUtils.isNotBlank(model.getAcceptStaff())) {
                    st[5] = modelTaskNewService.queryStaffName(model.getAcceptStaff());
                } else {
                    st[5] = "";
                }
                st[6] = (null == model.getCheckTaskStatus() ||  model.getCheckTaskStatus().intValue() == 0)? "未盘点" : "已提交";
                st[7] = null == model.getCheckTaskSubmitTime() ? "--" : DateUtils.getDateStrByFormat(model.getCheckTaskSubmitTime(), "yyyy.MM.dd HH:mm:ss");
                exptList.add(st);
            }
        }
        try {
            String fileName = "hasAssignTask_" + index + "@";
            File file = ExcelUtils.createExcelFile(fileName, exptList, titles);
            
            if (null != file) {
                OSSFileResult rsp = ossFileService.upload2OSSByFile(ExportConstants.OSSFileParams.BUCKET_EXPORT, fileName, file);
                if (FILE_UPLOAD_SUCCESS.equals(rsp.getRetFlag())) {
                    // 成功
                    String fileUrl = rsp.getFileUrl();
                    String staffID = staffId;
                    emailUtilsService.sendEmail(staffID, fileUrl, "已分配任务");
                } else {
                    // 失败不发送邮件
                    LOGGER.error("exportExcelModelByStoreEx failed. Rsp:{}", rsp);
                }
            } else {
                LOGGER.error("exportExcelModelByStoreEx failed. File is null");
            }
        } catch (Exception e) {
            LOGGER.error("exportHasAssignTaskEx failed.", e);
        }
        
    }

    @Override
    public void exportModelEffectEx(String staffId, String regionCode, String branchCode, String brandCode,
            String categoryCode, String storeCode, String comRangeName, String comGroupName, String commCode,
            Integer index, String month, String storeType) {
        LOGGER.info(
                "exportModelEffectEx.staffId:{},regionCode:{},branchCode:{},brandCode:{},categoryCode:{},storeCode:{},comRangeName:{},comGroupName:{},commCode:{},index:{},month:{},storeType:{}",
                new Object[] { staffId, regionCode, branchCode, brandCode, categoryCode, storeCode, comRangeName,
                        comGroupName, commCode, index, month, storeType });
        int pageSize = getExptCSVLimit();
        List<ModelEffectiveness> list = modelManageDaoService.queryModelEffectListEx(regionCode, branchCode,
                comRangeName, comGroupName, commCode, storeCode, brandCode, categoryCode, index, pageSize, month,
                storeType, EXPORT_SEARCH);
        String[] titles = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "门店类型", "品类编码", "品类名称",
                "品牌编码", "品牌名称", "商品编码", "商品名称", "商品组", "所属簇系列", "样机数量", "销售数量" };
        List<List<String>> data = null;
        if (CollectionUtils.isNotEmpty(list)) {
            // list转换-保留要插入到csv中的字段
            data = com.google.common.collect.Lists.transform(list, new Function<ModelEffectiveness, List<String>>() {
                @Override
                public List<String> apply(ModelEffectiveness input) {
                    List<String> msg = new ArrayList<String>();
                    msg.add(input.getRegionCode());
                    msg.add(input.getRegionName());
                    msg.add(input.getBranchCode());
                    msg.add(input.getBranchName());
                    msg.add(input.getStoreCode());
                    msg.add(input.getStoreName());
                    String storeTypeName = "";
                    if (StringUtils.isNotBlank(input.getStoreType())) {
                        storeTypeName = ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_INFOS_MAP.get(input.getStoreType());
                    }
                    msg.add(storeTypeName);
                    msg.add(input.getCateCode());
                    msg.add(input.getCategoryName());
                    msg.add(input.getBrand4code());
                    msg.add(input.getBrandName());
                    msg.add(input.getCommCode());
                    msg.add(input.getCommName());
                    msg.add(input.getComGroupName());
                    msg.add(input.getComRangeName());
                    msg.add(getStr(input.getModelCount()));
                    msg.add(getStr(input.getSaleCount()));
                    return msg;
                }
            });

        }
        try {
            String fileName = "modelEffect_" + index;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "样机有效性" + index,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportModelEffectEx failed.", e);
        }

    }
    
    @Override
    public void exportSaleModelExptEx(String staffId, String regionCode, String branchCode, String storeCode,
            Integer index, Integer isInStorage) {
        LOGGER.info(
                "exportSaleModelExptEx. staffId:{}, regionCode:{}, branchCode:{}, storeCode:{}, index:{}, isInStorage:{}",
                new Object[] { staffId, regionCode, branchCode, storeCode, index, isInStorage });
        int pageSize = getExptCSVLimit();
        List<SaleModelExptBean> list = modelManageDaoService.querySaleModelExptByStoreCode(regionCode, branchCode,
                storeCode, index, pageSize, isInStorage, EXPORT_SEARCH);

        String[] titles = new String[] { "大区编码", "大区名称", "分公司编码", "分公司名称", "门店编码", "门店名称", "门店类型", "品类编码", "品类名称",
                "品牌编码", "品牌名称", "商品编码", "商品名称", "库位", "样机属性", "盘点数量", "库存数量", "是否入库" };
        // list转换-保留要插入到csv中的字段
        List<List<String>> data = null;
        if (CollectionUtils.isNotEmpty(list)) {
            data = com.google.common.collect.Lists.transform(list, new Function<SaleModelExptBean, List<String>>() {
                @Override
                public List<String> apply(SaleModelExptBean saleModel) {
                    List<String> msg = new ArrayList<String>();
                    msg.add(saleModel.getRegionCode());
                    msg.add(saleModel.getRegionName());
                    msg.add(saleModel.getBranchCode());
                    msg.add(saleModel.getBranchName());
                    msg.add(saleModel.getStoreCode());
                    msg.add(saleModel.getStoreName());
                    String storeTypeName = "";
                    if (StringUtils.isNotBlank(saleModel.getStoreType())) {
                        storeTypeName = ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_INFOS_MAP.get(saleModel
                                .getStoreType());
                    }
                    msg.add(storeTypeName);
                    msg.add(saleModel.getCateCode());
                    msg.add(saleModel.getCategoryName());
                    msg.add(saleModel.getBrand4code());
                    msg.add(saleModel.getBrandName());
                    msg.add(saleModel.getCommCode());
                    msg.add(saleModel.getCommName());
                    msg.add(ModelConstant.getModelLibValue(saleModel.getStorage()));
                    msg.add(saleModel.getModelProperty());
                    msg.add(getStr(saleModel.getModelCount()));
                    msg.add(getStr(saleModel.getStockCount()));
                    msg.add(ModelConstant.STORAGE_FLAG.get(saleModel.getIsInStorage()) == null ? ""
                            : ModelConstant.STORAGE_FLAG.get(saleModel.getIsInStorage()));
                    return msg;
                }
            });
        }
        try {
            String fileName = "saleModelExpt-" + regionCode + "-" + index;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "财务异常样机清单" + index,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("财务样机异常列表导出exportSaleModelExptEx异常", e);
        } finally {
        }
    }
    
    @Override
    public void exportUnassignTaskEx(String staffId, String branchCode, String storeCode, String regionCode, String cateCode,
            Long taskId, Integer index) {
        int pageSize = getExptLimit();
        List<ModelTaskAssignDetailsBean> list = modelManageDaoService.queryTaskNoAssign(regionCode,
                branchCode, storeCode, cateCode, pageSize, index, taskId);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "大区名称",  "分公司名称", "门店名称", "品类名称", "分配人", "未分配品牌" };
        if (CollectionUtils.isNotEmpty(list)) {
            for (ModelTaskAssignDetailsBean model : list) {
                String[] st = new String[11];
                st[0] = model.getDisName();
                st[1] = model.getOrgName();
                st[2] = model.getStoreName();
                st[3] = model.getCateName();
                // 判断是否是指定的督导
                if (StringUtils.isNotBlank(model.getAcceptStaff())) {
                    st[4] = modelTaskNewService.queryStaffName(model.getAcceptStaff());
                } else {
                    // 查询品类下的督导
                    st[4] = modelTaskNewService.queryStaffName(model.getStoreCode(), model.getCateCode());
                }
                st[5] = model.getBranchName();
                exptList.add(st);
            }
        }
        try {
            String fileName = "noAssignTask_" + index + "@";
            File file = ExcelUtils.createExcelFile(fileName, exptList, titles);
            
            if (null != file) {
                OSSFileResult rsp = ossFileService.upload2OSSByFile(ExportConstants.OSSFileParams.BUCKET_EXPORT, fileName, file);
                if (FILE_UPLOAD_SUCCESS.equals(rsp.getRetFlag())) {
                    // 成功
                    String fileUrl = rsp.getFileUrl();
                    String staffID = staffId;
                    emailUtilsService.sendEmail(staffID, fileUrl, "未分配任务");
                } else {
                    // 失败不发送邮件
                    LOGGER.error("exportExcelModelByStoreEx failed. Rsp:{}", rsp);
                }
            } else {
                LOGGER.error("exportExcelModelByStoreEx failed. File is null");
            }
        } catch (Exception e) {
            LOGGER.error("exportUnassignTaskEx failed.", e);
        }
    }

    @Override
    public ReturnMsg<ModelTaskInfoVo> queryTaskInfoByID(Long taskId) {
        LOGGER.info("queryTaskInfoByID for taskId:{} ", taskId);
        
        ModelTaskMainBean modelTaskMainBean = modelManageDaoService.queryModelTaskDetail(taskId);
        ReturnMsg<ModelTaskInfoVo> ret = new ReturnMsg<ModelTaskInfoVo>();
        ModelTaskInfoVo modelTaskInfoVo = new ModelTaskInfoVo();
       
        if(modelTaskMainBean == null){
            LOGGER.error("queryTaskInfoByID failed  modelTaskMainBean is null . taskId is :{}",taskId);
            ret.setError(ErrorCodeConstants.ERR_0028);
            return ret;
        }
        
        modelTaskInfoVo.setStartTime(modelTaskMainBean.getStartTime() == null?"--": DateUtils.getDateStrByFormat(modelTaskMainBean.getStartTime(), "yyyy-MM-dd"));
        modelTaskInfoVo.setEndTime(modelTaskMainBean.getEndTime() == null?"--": DateUtils.getDateStrByFormat(modelTaskMainBean.getEndTime(), "yyyy-MM-dd"));
        modelTaskInfoVo.setStorageCode(modelTaskMainBean.getStorageCode());
        if(StringUtils.isNotBlank(modelTaskMainBean.getStorageCode())){
            modelTaskInfoVo.setStorageName(modelTaskMainBean.getStorageCode()+ " " + ModelConstant.MODEL_LIB_INFOS.get(modelTaskMainBean.getStorageCode()));
        }
        modelTaskInfoVo.setTaskId(taskId);
        if(modelTaskMainBean.getTaskType() !=null){
            modelTaskInfoVo.setTaskType(modelTaskMainBean.getTaskType().toString());
            if(ModelConstant.TASK_TYPE_HQ == modelTaskMainBean.getTaskType()){
                modelTaskInfoVo.setTaskTypeDesc("总部");
            }else if(ModelConstant.TASK_TYPE_REGION == modelTaskMainBean.getTaskType()){
                modelTaskInfoVo.setTaskTypeDesc("大区");
            }else{
                modelTaskInfoVo.setTaskTypeDesc("--");
            }
        }
        ret.setData(modelTaskInfoVo);
        return ret;
    
    }

    @Override
    public ReturnMsg<ModelTaskMonitorVo> queryTaskMonitor(String branchCode, String regionCode, Long taskId, int pageSize, int pageNo) {

        LOGGER.info("queryTaskMonitor for branchCode:{},regionCode:{},taskId:{}",branchCode,regionCode,taskId);

        ReturnMsg<ModelTaskMonitorVo>  result = new  ReturnMsg<ModelTaskMonitorVo>();
        ModelTaskMonitorVo resultBean = null;

        String keyIndex = "";
        if (StringUtils.isNotBlank(branchCode)) {
            //分公司
            keyIndex = branchCode;
        }else  if (StringUtils.isNotBlank(regionCode)) {
            //大区
            keyIndex = regionCode;
        }else {
            //全国
            keyIndex = MODEL_MONITOR_HQ;
        }
        
        String cacheKey = String.format(CacheKeyConstants.MODEL_MONITOR, taskId.toString(),keyIndex);
        
        if(cacheUtils.exists(cacheKey)){
            resultBean =  cacheUtils.hget(cacheKey, String.valueOf(pageNo),ModelTaskMonitorVo.class);
            result.setData(resultBean);
        }else{
            //查询样机 门店、品类、品牌监控统计数据
            List<ModelTaskMonitorDetailVo> list   =  modelManageDaoService.queryTaskMonitorList(branchCode,regionCode,taskId);
            if(CollectionUtils.isNotEmpty(list)){
                redisCacheMonitorInfo( branchCode,  regionCode,  cacheKey,  pageSize,  pageNo,list);
                resultBean =  cacheUtils.hget(cacheKey, String.valueOf(pageNo),ModelTaskMonitorVo.class);
                result.setData(resultBean);
            }else{
                ModelTaskMonitorVo modelTaskMonitorVo = new ModelTaskMonitorVo();
                ModelTaskMonitorDetailVo totalMonitor = new ModelTaskMonitorDetailVo();
                totalMonitor.setBrandComNum("0");
                totalMonitor.setBrandComNumEx("0");
                totalMonitor.setBrandDisNum("0");
                totalMonitor.setBrandTotalNum("0");
                totalMonitor.setBrandComRate("0.00");
                
                totalMonitor.setCateComNum("0");
                totalMonitor.setCateDisNum("0");
                totalMonitor.setCateTotalNum("0");
                totalMonitor.setCateComRate("0.00");
                
                totalMonitor.setStoreComNum("0");
                totalMonitor.setStoreDisNum("0");
                totalMonitor.setStoreTotalNum("0");
                totalMonitor.setStoreComRate("0.00");
                
                if(StringUtils.isNotBlank(branchCode)){
                    totalMonitor.setAreaCode(branchCode);
                }else  if(StringUtils.isNotBlank(regionCode)){
                    totalMonitor.setAreaCode(regionCode);
                }
                
                modelTaskMonitorVo.setTotalStatistics(totalMonitor);
                modelTaskMonitorVo.setDataUpdateTime(DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_TIME_PATTERN));
                modelTaskMonitorVo.setBranchCode(branchCode);
                modelTaskMonitorVo.setRegionCode(regionCode);
                modelTaskMonitorVo.setTotalSize(String.valueOf(list.size()));
                if(StringUtils.isNotBlank(branchCode)){
                    modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.BRANCH_LEVEL));
                }else  if(StringUtils.isNotBlank(regionCode)){
                    modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.REGION_LEVEL));
                }else{
                    modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.HQ_LEVEL));
                }
                
                result.setData(modelTaskMonitorVo);
            }
        }
        return result;
    }

    private void redisCacheMonitorInfo(String branchCode, String regionCode, String cacheKey, int pageSize, int pageNo, List<ModelTaskMonitorDetailVo> list) {
        ModelTaskMonitorVo modelTaskMonitorVo = new ModelTaskMonitorVo();
        ModelTaskMonitorDetailVo totalMonitor = new ModelTaskMonitorDetailVo();
        String storeTotalNum = "0";
        String storeComNum = "0";
        String storeDisNum = "0";
        String cateTotalNum = "0";
        String cateComNum = "0";
        String cateDisNum = "0";
        String brandTotalNum = "0";
        String brandComNum = "0";
        String brandComNumEx = "0";
        String brandDisNum = "0";
        for(ModelTaskMonitorDetailVo item : list ){
            if(item == null){
                continue;
            }
            item.setBrandComRate( DJStringUtils.calculateRateString(item.getBrandComNum(), item.getBrandTotalNum()));
            
            item.setCateComRate( DJStringUtils.calculateRateString(item.getCateComNum(), item.getCateTotalNum()));
            
            item.setStoreComRate( DJStringUtils.calculateRateString(item.getStoreComNum(), item.getStoreTotalNum()));
            
           brandDisNum = DJStringUtils.additionEx(brandDisNum, item.getBrandDisNum());
           brandComNum = DJStringUtils.additionEx(brandComNum, item.getBrandComNum());
           brandTotalNum = DJStringUtils.additionEx(brandTotalNum, item.getBrandTotalNum());
           brandComNumEx = DJStringUtils.additionEx(brandComNumEx, item.getBrandComNumEx());

           cateDisNum = DJStringUtils.additionEx(cateDisNum, item.getCateDisNum());
           cateComNum = DJStringUtils.additionEx(cateComNum, item.getCateComNum());
           cateTotalNum = DJStringUtils.additionEx(cateTotalNum, item.getCateTotalNum());
           

           storeDisNum = DJStringUtils.additionEx(storeDisNum, item.getStoreDisNum());
           storeComNum = DJStringUtils.additionEx(storeComNum, item.getStoreComNum());
           storeTotalNum = DJStringUtils.additionEx(storeTotalNum, item.getStoreTotalNum());
           
        }
        

        totalMonitor.setBrandComNum(brandComNum);
        totalMonitor.setBrandComNumEx(brandComNumEx);
        totalMonitor.setBrandDisNum(brandDisNum);
        totalMonitor.setBrandTotalNum(brandTotalNum);
        totalMonitor.setBrandComRate( DJStringUtils.calculateRateString(brandComNum,brandTotalNum));
        
        totalMonitor.setCateComNum(cateComNum);
        totalMonitor.setCateDisNum(cateDisNum);
        totalMonitor.setCateTotalNum(cateTotalNum);
        totalMonitor.setCateComRate( DJStringUtils.calculateRateString(cateComNum, cateTotalNum));
        
        totalMonitor.setStoreComNum(storeComNum);
        totalMonitor.setStoreDisNum(storeDisNum);
        totalMonitor.setStoreTotalNum(storeTotalNum);
        totalMonitor.setStoreComRate( DJStringUtils.calculateRateString(storeComNum, storeTotalNum));
        
        if(StringUtils.isNotBlank(branchCode)){
            totalMonitor.setAreaCode(branchCode);
        }else  if(StringUtils.isNotBlank(regionCode)){
            totalMonitor.setAreaCode(regionCode);
        }
        
        modelTaskMonitorVo.setTotalStatistics(totalMonitor);
        modelTaskMonitorVo.setDataUpdateTime(DateUtils.getDateStrByFormat(new Date(), DateUtils.DEFAULT_TIME_PATTERN));
        modelTaskMonitorVo.setBranchCode(branchCode);
        modelTaskMonitorVo.setRegionCode(regionCode);
        modelTaskMonitorVo.setTotalSize(String.valueOf(list.size()));
        if(StringUtils.isNotBlank(branchCode)){
            modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.BRANCH_LEVEL));
        }else  if(StringUtils.isNotBlank(regionCode)){
            modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.REGION_LEVEL));
        }else{
            modelTaskMonitorVo.setCurrLevel(String.valueOf(OrgInfo.ORG_LEVEL.HQ_LEVEL));
        }
        
        if(list.size() <= pageSize){
            modelTaskMonitorVo.setRecords(list);
            cacheUtils.hsetWithMyExpireTime(cacheKey, String.valueOf(pageNo), modelTaskMonitorVo, CacheKeyConstants.MODEL_MONITOR_EXPIRE_TIME);
        }else{
            List<ModelTaskMonitorDetailVo> tmpList = new ArrayList<ModelTaskMonitorDetailVo>();
            int pageNoIndex = 1;
            for(ModelTaskMonitorDetailVo item : list ){
                if(tmpList.size() >= pageSize){
                    modelTaskMonitorVo.setRecords(tmpList);
                    cacheUtils.hsetWithMyExpireTime(cacheKey, String.valueOf(pageNoIndex), modelTaskMonitorVo, CacheKeyConstants.MODEL_MONITOR_EXPIRE_TIME);
                    pageNoIndex++;
                    tmpList.clear();
                }

                if(item != null){
                    tmpList.add(item);
                }
            
            }
            
            if(tmpList.size() > 0){
                modelTaskMonitorVo.setRecords(tmpList);
                cacheUtils.hsetWithMyExpireTime(cacheKey, String.valueOf(pageNoIndex), modelTaskMonitorVo, CacheKeyConstants.MODEL_MONITOR_EXPIRE_TIME);
            }
        }
    }

    @Override
    public void exportExcelModelTask(String staffId, String regionCode, String branchCode, String storeCode,
            String cateCode, String brandCode, String taskStatus, String assignStatus, Long taskId, Integer index) {

        int pageSize = getExptLimit();
        List<ModelTaskAssignDetailsBean> list = modelManageDaoService.queryAssignAllList(taskId, regionCode, branchCode, storeCode, cateCode, brandCode, taskStatus, assignStatus, pageSize, index);
        String[] titles = new String[] { "大区名称",  "分公司名称", "门店名称", "品类名称", "品牌名称", "盘点人",
            "盘点状态", "盘点时间","分配人","分配时间" };
        List<List<String>> data = null;
        if (CollectionUtils.isNotEmpty(list)) {
            // list转换-保留要插入到csv中的字段
            data = com.google.common.collect.Lists.transform(list, new Function<ModelTaskAssignDetailsBean, List<String>>() {
                @Override
                public List<String> apply(ModelTaskAssignDetailsBean bean) {
                    List<String> msg = new ArrayList<String>();
                    msg.add(bean.getDisName());
                    msg.add(bean.getOrgName());
                    msg.add(bean.getStoreName());
                    msg.add(bean.getCateName());
                    msg.add(bean.getBranchName());
                    if(ModelConstant.TASK_ASSIGN_STATUS_NO.equals(bean.getAssignStatus())){
                        msg.add("--");
                        msg.add(ModelConstant.CHECK_TASK_STATUS_MAP.get(bean.getCheckTaskStatus()));
                        msg.add("--");
                        msg.add("--");
                        msg.add("--");
                    }else{
                        if (StringUtils.isNotBlank(bean.getAcceptStaff())) {
                            msg.add(modelTaskNewService.queryStaffName(bean.getAcceptStaff()));
                        }else{
                            msg.add("--");
                        }
                        
                        msg.add(ModelConstant.CHECK_TASK_STATUS_MAP.get(bean.getCheckTaskStatus()));

                        if(ModelConstant.CHECK_TASK_STATUS_NO.equals(bean.getCheckTaskStatus())){
                            msg.add("--");
                        }else{
                            msg.add(null == bean.getCheckTaskSubmitTime() ? "--" : DateUtils.getDateStrByFormat(bean.getCheckTaskSubmitTime(), "yyyy.MM.dd HH:mm:ss"));
                        }
                        
                        // 判断是否是指定的督导
                        if (StringUtils.isNotBlank(bean.getAssignStaff())) {
                            msg.add(modelTaskNewService.queryStaffName(bean.getAssignStaff()));
                        } else {
                            // 查询品类下的督导
                            msg.add(modelTaskNewService.queryStaffName(bean.getStoreCode(), bean.getCateCode()));
                        }
                        msg.add(null == bean.getAssignTime() ? "--" : DateUtils.getDateStrByFormat(bean.getAssignTime(), "yyyy.MM.dd HH:mm:ss"));
                    }
  
                    return msg;
                }
            });

        }
        try {
            String fileName = "modelTask_" + index ;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "样机任务明细" + index,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportExcelModelTask failed.", e);
        }
        
    
    }

    @Override
    public void exportExcelModelMonitor(String staffId, String regionCode, String branchCode, Long taskId) {
        List<ModelTaskMonitorDetailVo> list   =  modelManageDaoService.queryTaskMonitorList(branchCode,regionCode,taskId);
        String codeTitle = "";
        String nameTitle = "";
        if(StringUtils.isNotBlank(branchCode)){
            codeTitle = "门店编码";
            nameTitle = "门店名称";
        }else if(StringUtils.isNotBlank(regionCode)){
            codeTitle = "分公司编码";
            nameTitle = "分公司名称";
        }else{
            codeTitle = "大区编码";
            nameTitle = "大区名称";
        }
                
        String[] titles = new String[] { codeTitle,nameTitle,  "任务门店数", "已完成门店", "未完成门店", "门店完成率", "任务品类数",
            "已分配品类", "未分配品类","品类分配率","任务品牌数" ,"已分配品牌", "未分配品牌","品牌分配率","已完成品牌"};
        List<List<String>> data = null;
        if (CollectionUtils.isNotEmpty(list)) {
            // list转换-保留要插入到csv中的字段
            data = com.google.common.collect.Lists.transform(list, new Function<ModelTaskMonitorDetailVo, List<String>>() {
                @Override
                public List<String> apply(ModelTaskMonitorDetailVo bean) {
                    List<String> msg = new ArrayList<String>();
                    msg.add(bean.getAreaCode());
                    msg.add(bean.getAreaName());
                    
                    msg.add(bean.getStoreTotalNum());
                    msg.add(bean.getStoreComNum());
                    msg.add(bean.getStoreDisNum());
                    
                    msg.add(DJStringUtils.calculateRateString(bean.getStoreComNum(), bean.getStoreTotalNum()) +"%");
                    
                    msg.add(bean.getCateTotalNum());
                    msg.add(bean.getCateComNum());
                    msg.add(bean.getCateDisNum());
                    msg.add(DJStringUtils.calculateRateString(bean.getCateComNum(), bean.getCateTotalNum()) +"%");

                    msg.add(bean.getBrandTotalNum());
                    msg.add(bean.getBrandComNum());
                    msg.add(bean.getBrandDisNum());
                    msg.add(DJStringUtils.calculateRateString(bean.getBrandComNum(), bean.getBrandTotalNum()) +"%");
                    msg.add(bean.getBrandComNumEx());
                    return msg;
                }
            });

        }
        try {
            String fileName = "modelMonitor"  ;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "样机监控",
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportExcelModelTask failed.", e);
        }
    }

    @Override
    public ReturnMsg<List<DownloadModelListBean>> queryDownloadMonths() {
        ReturnMsg<List<DownloadModelListBean>> ret = new ReturnMsg<List<DownloadModelListBean>>();
        List<DownloadModelListBean> result = modelManageDaoService.queryDownloadMonths();
        ret.setData(result);
        return ret;
    }
 
    @Override
    public ReturnMsg<List<DownloadModelListBean>> queryDownloadUrlList(String month) {
        ReturnMsg<List<DownloadModelListBean>> ret = new ReturnMsg<List<DownloadModelListBean>>();
        List<DownloadModelListBean> result = modelManageDaoService.queryDownloadUrlList(month);
        ret.setData(result);
        return ret;
    }
}
